Django 如何发送选项字段的关联值
我有一个名为Django 如何发送选项字段的关联值,django,django-rest-framework,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使
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
。如何使其发送第二个文本值作为响应
以下是我的序列化程序的一部分:
class TicketSerializer(serializers.ModelSerializer):
status = serializers.ChoiceField(choices=Ticket.STATUS_CHOICES)
class Meta:
model = Ticket
fields = ('status', )
API通常用于获取数据,而不是数据的UI表示。在
('1','Choice 1')
中,'1'
是要在任何地方存储和使用的值,'Choice 1'
是我们需要时(在UI即模板中)需要显式使用的UI表示形式
DjangoAdmin是一个完整的Django应用程序,因此它显式地使用UI表示。如果您使用Django表单,您也需要显式地使用它。它不是自动使用的
在模板中,如果您执行{{my\u form\u choice\u field.value}
操作,它将使用'1'
而不是'choice 1'
。您需要显式使用{{my\u form\u choice\u field.get\u my\u form\u choice\u field\u display}
(在UI层中)来获取'choice 1'
所以,正如我从API开始所说的,API通常用于获取数据,而不是它的UI表示。这就是为什么(与DJANGO一样)DjangoRestFramework也只使用原始值,而不使用其UI表示
如果您确实想返回UI表示,现在回答您的问题。然后,您需要重写BaseSerializer的to_表示法
方法,以将值替换为其UI表示法,并重写to_internal_值
以在保存时将UI表示法替换回值
您可以看到一个示例(从文档中)
引用上面链接的文档示例代码
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)
API通常用于获取数据,而不是数据的UI表示。在
('1','Choice 1')
中,'1'
是要在任何地方存储和使用的值,'Choice 1'
是我们需要时(在UI即模板中)需要显式使用的UI表示形式
DjangoAdmin是一个完整的Django应用程序,因此它显式地使用UI表示。如果您使用Django表单,您也需要显式地使用它。它不是自动使用的
在模板中,如果您执行{{my\u form\u choice\u field.value}
操作,它将使用'1'
而不是'choice 1'
。您需要显式使用{{my\u form\u choice\u field.get\u my\u form\u choice\u field\u display}
(在UI层中)来获取'choice 1'
所以,正如我从API开始所说的,API通常用于获取数据,而不是它的UI表示。这就是为什么(与DJANGO一样)DjangoRestFramework也只使用原始值,而不使用其UI表示
如果您确实想返回UI表示,现在回答您的问题。然后,您需要重写BaseSerializer的to_表示法
方法,以将值替换为其UI表示法,并重写to_internal_值
以在保存时将UI表示法替换回值
您可以看到一个示例(从文档中)
引用上面链接的文档示例代码
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)
下面的方法解决了这个问题。我们可以为选项创建自定义字段
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建议的解决方案类似,但更为简洁。以下方法解决了此问题。我们可以为选项创建自定义字段
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提出的解决方案类似,但更为清洁