选择字段中的 Return display_name

Return display_name in ChoiceField

我正在使用 ModelViewSetModelSerializer 在 DRF 中实现一些 REST API。我所有的 API 都使用 JSON 格式,我的一些模型使用 ChoiceField 字段,例如:

MyModel(models.Model):
     KEY1 = 'Key1'
     KEY2 = 'Key2'
     ATTRIBUTE_CHOICES = (
         (KEY1, 'Label 1'),
         (KEY2, 'Label 2'))
     attribute = models.CharField(max_length=4, 
                                  choices=ATTRIBUTE_CHOICES, default=KEY1)

我的问题是默认情况下 DRF 总是 returns(并接受)JSON 消息的这些选择的键(参见 here),但我想使用标签,因为我认为它更一致和清楚地了解谁将使用那些 APIs。有什么建议吗?

除了重写序列化程序之外别无他法。请看一下,看看它是如何完成的。

我找到了一个可能的解决方案,即定义我自己的字段如下:

class MyChoiceField(serializers.ChoiceField):

    def to_representation(self, data):
        if data not in self.choices.keys():
            self.fail('invalid_choice', input=data)
        else:
            return self.choices[data]

    def to_internal_value(self, data):
        for key, value in self.choices.items():
            if value == data:
                 return key
        self.fail('invalid_choice', input=data)

它的工作方式与 ChoiceField 相同,但 returns 接受标签而不是键。

以前的答案对我帮助很大,但对我不起作用,因为我使用的是 Django 版本 3 和 DRF 版本 3.11,所以我想到了这个:

# models.py
class Ball(models.Model):
    
    class Types(models.TextChoice):
        VOLLYBALL = 'VB', gettext_lazy('VollyBall')
        FOOTBALL = 'FB', gettext_lazy('FootBall')

    type = models.CharField(max_length=2, choices=Types.choices)
# serializers.py

class CustomChoiceField(serializers.ChoiceField):

    def to_representation(self, value):
        if value in ('', None):
            return value

        choice_dict = {str(key): key.label for key in self.choices}
        return choice_dict.get(str(value), value)

    def to_internal_value(self, data):
        if data == '' and self.allow_blank:
            return ''

        try:
            choice_dict = {key.label: str(key) for key in self.choices}
            return choice_dict[str(data)]
        except KeyError:
            self.fail('invalid_choice', input=data)

class BallSerializer(serializers.ModelSerializer):
    type = CustomChoiceField(choices=Book.Types)
    
    class Meta:
        model = Book
        fields = ['type']