Django Rest Framework 如何更新 SerializerMethodField
Django Rest Framework How to update SerializerMethodField
我有一个像这样的序列化程序:
class PersonSerializer(serializers.ModelSerializer):
gender = serializers.SerializerMethodField()
bio = BioSerializer()
class Meta:
model = Person
fields = UserSerializer.Meta.fields + ('gender', 'bio',)
def get_gender(self, obj):
return obj.get_gender_display()
我在执行 GET 请求时用它来显示 "Male" 和 "Female"(代替 "F" 的 "M")。
这很好用。
但是现在我正在为模型编写补丁方法并且SerializerMethodField()
有read_only=True
。所以我没有在 serializer.validated_data()
中为性别字段传递值。如何克服这个问题?
因此,如果我理解正确的话,您想在 PATCH 请求中发送 {'gender': 'Male'}。
因此,您必须告诉您的序列化程序如何将您的表示形式(即 'Male' 转换为内部值。
如您所愿see in source,SerializerMethodField 仅涵盖从内部值到表示的转换。
您可以实施自定义 SerializerField 来执行必要的转换。天真的实现可能是这样的:
class GenderSerializerField(serializers.Field):
VALUE_MAP = {
'M': 'Male',
'F': 'Female'
}
def to_representation(self, obj):
return self.VALUE_MAP[obj]
def to_internal_value(self, data):
return {k:v for v,k in self.VALUE_MAP.items()}[data]
class PersonSerializer(serializers.ModelSerializer):
gender = GenderSerializerField()
...
请注意,此内容未经测试且缺乏任何验证,请查看 DRF docs on custom fields。
除了公认的答案外,还可以有其他更简单的钩子。如果 'create' 和 'update' 在修改 gender
字段之前如您所愿地工作,那么您可以按照以下步骤将创建和更新请求的所有内容设置为默认值。
- 不要用户
SerializerMethodField
。而是覆盖序列化程序表示。
class PersonSerializer(serializers.ModelSerializer):
bio = BioSerializer()
class Meta:
model = Person
fields = UserSerializer.Meta.fields + ('bio',)
def to_representation(self, obj):
ret = super().to_representation(obj)
ret['gender'] = obj.get_gender_display()
return ret
- 覆盖
__init__
方法。
.
class PersonSerializer(serializers.ModelSerializer):
bio = BioSerializer()
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
try:
if self.context['request'].method in ['GET']:
self.fields['gender'] = serializers.SerializerMethodField()
except KeyError:
pass
class Meta:
model = Person
fields = UserSerializer.Meta.fields + ('bio',)
def get_gender(self, obj):
return obj.get_gender_display()
我有一个像这样的序列化程序:
class PersonSerializer(serializers.ModelSerializer):
gender = serializers.SerializerMethodField()
bio = BioSerializer()
class Meta:
model = Person
fields = UserSerializer.Meta.fields + ('gender', 'bio',)
def get_gender(self, obj):
return obj.get_gender_display()
我在执行 GET 请求时用它来显示 "Male" 和 "Female"(代替 "F" 的 "M")。
这很好用。
但是现在我正在为模型编写补丁方法并且SerializerMethodField()
有read_only=True
。所以我没有在 serializer.validated_data()
中为性别字段传递值。如何克服这个问题?
因此,如果我理解正确的话,您想在 PATCH 请求中发送 {'gender': 'Male'}。
因此,您必须告诉您的序列化程序如何将您的表示形式(即 'Male' 转换为内部值。
如您所愿see in source,SerializerMethodField 仅涵盖从内部值到表示的转换。
您可以实施自定义 SerializerField 来执行必要的转换。天真的实现可能是这样的:
class GenderSerializerField(serializers.Field):
VALUE_MAP = {
'M': 'Male',
'F': 'Female'
}
def to_representation(self, obj):
return self.VALUE_MAP[obj]
def to_internal_value(self, data):
return {k:v for v,k in self.VALUE_MAP.items()}[data]
class PersonSerializer(serializers.ModelSerializer):
gender = GenderSerializerField()
...
请注意,此内容未经测试且缺乏任何验证,请查看 DRF docs on custom fields。
除了公认的答案外,还可以有其他更简单的钩子。如果 'create' 和 'update' 在修改 gender
字段之前如您所愿地工作,那么您可以按照以下步骤将创建和更新请求的所有内容设置为默认值。
- 不要用户
SerializerMethodField
。而是覆盖序列化程序表示。
class PersonSerializer(serializers.ModelSerializer):
bio = BioSerializer()
class Meta:
model = Person
fields = UserSerializer.Meta.fields + ('bio',)
def to_representation(self, obj):
ret = super().to_representation(obj)
ret['gender'] = obj.get_gender_display()
return ret
- 覆盖
__init__
方法。 .
class PersonSerializer(serializers.ModelSerializer):
bio = BioSerializer()
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
try:
if self.context['request'].method in ['GET']:
self.fields['gender'] = serializers.SerializerMethodField()
except KeyError:
pass
class Meta:
model = Person
fields = UserSerializer.Meta.fields + ('bio',)
def get_gender(self, obj):
return obj.get_gender_display()