如何发送选择字段的关联值

时间:2016-05-16 06:57:16

标签: django django-rest-framework

我有一个名为Ticket的模型,其中包含选择字段status

STATUS_CHOICES = (
    ('1', 'Open'),
    ('2', 'Resolved'),
    ('3', 'Won\'t fix')
)
status = models.CharField(
    "Status",
    max_length=1,
    choices=STATUS_CHOICES,
    blank=False,
    default='1'
)

我正在为API使用Django rest框架。默认模型序列化程序发送第一个选择值,即1而不是Open。如何让它发送第二个文本值作为回应。

这是我的Serializer的一部分:

class TicketSerializer(serializers.ModelSerializer):
    status = serializers.ChoiceField(choices=Ticket.STATUS_CHOICES)        

    class Meta:
        model = Ticket
        fields = ('status', )

2 个答案:

答案 0 :(得分:4)

API通常用于获取数据,而不是数据的UI表示。在('1', 'Choice 1')中,'1'是要在任何地方存储和使用的值,'Choice 1'是我们需要在需要时显式使用的UI表示(在UI即模板中)。 / p>

DjangoAdmin是一个完整的Django应用程序,因此它显式使用UI表示。如果你使用Django Forms,你也需要明确地使用它。它不会自动使用。

如果您{{ my_form_choice_field.value }},则在模板中,它将使用'1'而不是'Choice 1'。您需要明确使用{{ my_form_choice_field.get_my_form_choice_field_display }} (在UI图层中)来获取'Choice 1'

因此,当我开始使用API​​时,通常用于获取数据,而不是它的UI表示。这就是为什么(JUST LIKE DJANGO)DjangoRestFramework也只使用原始值而不是UI表示。

现在回答你的问题,如果你真的想要返回UI表示。然后,您需要覆盖BaseSerializer的to_representation方法以使用其UI表示替换值,并覆盖to_internal_value以在保存时将UI表示替换回值。

您可以看到一个示例(来自文档)here

引用上面链接的文档示例代码

class HighScoreSerializer(serializers.BaseSerializer):
    def to_internal_value(self, data):
        score = data.get('score')
        player_name = data.get('player_name')

        # Perform the data validation.
        if not score:
            raise ValidationError({
                'score': 'This field is required.'
            })
        if not player_name:
            raise ValidationError({
                'player_name': 'This field is required.'
            })
        if len(player_name) > 10:
            raise ValidationError({
                'player_name': 'May not be more than 10 characters.'
            })

        # Return the validated values. This will be available as
        # the `.validated_data` property.
        return {
            'score': int(score),
            'player_name': player_name
        }

    def to_representation(self, obj):
        return {
            'score': obj.score,
            'player_name': obj.player_name
        }

    def create(self, validated_data):
        return HighScore.objects.create(**validated_data)

答案 1 :(得分:1)

以下方法解决了这个问题。我们可以为Choices创建一个自定义字段。

class ChoicesField(serializers.Field):
    def __init__(self, choices, **kwargs):
        self._choices = choices
        super(ChoicesField, self).__init__(**kwargs)

    def to_representation(self, obj):
        return self._choices[int(obj) - 1]  # obj is the first value

    def to_internal_value(self, data):
        return getattr(self._choices, data)

这类似于Tahir建议的解决方案,但更清洁。