如何从模型类更改django rest框架的ChoiceField的选择?

如何从模型类更改django rest框架的ChoiceField的选择?,django,django-rest-framework,choicefield,Django,Django Rest Framework,Choicefield,Th models.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', bla

Th models.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
当我创建代码对象的距离而不是CharField时,是否可以使用ChoiseField来选择代码内部的类型

可能的解决办法 我找到了一个可能的解决方案,我将类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()
        ])
并在中更改代码序列化程序:

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',)
这个解决方案的唯一缺陷是我需要两个字段而不是一个(type,choise_of_type)