我有一个名为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', )
答案 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建议的解决方案,但更清洁。