模型.py 是:
from django.db import models
class Type(models.Model):
letter = models.CharField(max_length = 1)
name = models.CharField(max_length = 10)
class Code(models.Model):
type = models.ForeignKey(Type, related_name = 'code', blank = True, default = None)
serializers.py 是:
import collections
from rest_framework import serializers
from code.models import Type, Code
class TypeSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Type
fields = ('letter','name')
class TypeField(serializers.HyperlinkedModelSerializer):
class Meta:
model = Type
fields = ('letter',)
class CodeSerializer(serializers.HyperlinkedModelSerializer):
type = TypeField() #serializers.ChoiceField(???)
def create(self, validated_data):
c = Code()
c.type = Type.objects.get(letter = validated_data['type']['letter'])
c.save()
return c
class Meta:
model = Code
fields = ('type',)
views.py 是:
from rest_framework import viewsets
from code.models import Code, Type
from code.serializers import CodeSerializer, TypeSerializer
class CodeViewSet(viewsets.ModelViewSet):
queryset = Code.objects.all()
serializer_class = CodeSerializer
class TypeViewSet(viewsets.ModelViewSet):
queryset = Type.objects.all()
serializer_class = TypeSerializer
是否可以使用 ChoiseField 来选择代码中的类型,当我创建代码对象的实例而不是 CharField 时?
可能的解决方案
我找到了一个可能的解决方案,我将类 ChoiseField 派生到 DynamicChoiceField
class DynamicChoiceField(serializers.ChoiceField):
def __init__(self, **kwargs):
super(DynamicChoiceField, self).__init__([],**kwargs)
def set_choices(self, choices):
pairs = [
isinstance(item, (list, tuple)) and len(item) == 2
for item in choices
]
if all(pairs):
self.choices = OrderedDict([(key, display_value) for key, display_value in choices])
else:
self.choices = OrderedDict([(item, item) for item in choices])
self.choice_strings_to_values = dict([
(six.text_type(key), key) for key in self.choices.keys()
])
并将 CodeSerializer 更改为:
class CodeSerializer(serializers.HyperlinkedModelSerializer):
type = TypeField(read_only=True)
choise_of_type = DynamicChoiceField(allow_blank=False, write_only=True)
def __init__(self, *args, **kwargs):
types = Type.objects.all()
choices = [(t.letter,t.name) for t in types]
self.fields['choise_of_type'].set_choices(choices)
super(CodeSerializer, self).__init__(*args, **kwargs)
def create(self, validated_data):
c = Code()
c.type = Type.objects.get(letter = validated_data['choise_of_type'])
c.save()
return c
class Meta:
model = Code
fields = ('type', 'choise_of_type',)
该解决方案的唯一缺陷是我只需要两个字段(类型,choise_of_type)