Django Rest Framework How to update SerializerMethodField
Solution 1
So if I understand you correctly, you want to send {'gender': 'Male'} in your PATCH request.
Therefor, you have to tell your serializer how to convert your representation i.e. 'Male' into the internal value.
As you can see in source, SerializerMethodField only covers the conversion from internal value to the representation.
You can implement a custom SerializerField that performs the necessary conversions. A naive implementation could something like this:
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()
...
Note that this untested and lacks any validation, check out the DRF docs on custom fields.
Solution 2
Aside from accepted answer, there can be other simpler hooks. If 'create' and 'update' worked as you wanted before modifiying gender
field, then you can do as follow to get everything to default for create and update requests.
- Do not user
SerializerMethodField
. Instead override serializer representation.
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
- Override the
__init__
method . .
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()
Kishan Mehta
Curious learner. Believe in hard work. Mostly code in Python, sometimes JS.
Updated on June 07, 2022Comments
-
Kishan Mehta almost 2 years
I have a serializer like this:
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()
I used this to display "Male" and "Female"(insted of "M" of "F") while performing GET request.
This works fine.
But now I am writing an patch method for the model and
SerializerMethodField()
hasread_only=True
. So I am not getting value passed for gender field inserializer.validated_data()
. How to overcome this issue?