Using Django Rest Framework 3.6.3, I have a choices CharField in my model:
# models.py
class User(AbstractUser):
GENDER_CHOICES = (
('M', 'Male'),
('F', 'Female'),
)
gender = models.CharField(max_length=1, choices=GENDER_CHOICES)
# viewsets.py
class UserViewSet(viewsets.ModelViewSet):
queryset = User.objects.all()
serializer_class = UserSerializer
I'm posting to the endpoint:
{ 'gender': 'M' }
When I GET the endpoint, I want it to show:
{ 'gender': 'Male' }
With the following serializer, it displays the display value of the choice (Male) instead of the value (M), but it doesn't save:
# serializers.py
class UserSerializer(serializers.ModelSerializer):
# for some reason on save, gender is None??
gender = serializers.SerializerMethodField()
class Meta:
model = User
def get_gender(self, obj):
return obj.get_gender_display()
If I add a to_internal_value
method then it works fine (displays the gender choice display value, but also saves:
# serializers.py
class UserSerializer(serializers.ModelSerializer):
gender = serializers.SerializerMethodField()
class Meta:
model = User
def get_gender(self, obj):
return obj.get_gender_display()
def to_internal_value(self, data):
# if I add a to_internal_value that does nothing, it saves??
return data
Why does this work? Is there a more obvious way I should write this?
Overriding to_internal_value
works because you bypass the per field to_internal_value
call.
An alternative solution would be:
class UserSerializer(serializers.ModelSerializer):
gender = serializers.ChoiceField(choices=User.GENDER_CHOICES)
class Meta:
model = User
why don't you place get_gender_display
inside fields
? like this:
# serializers.py
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = 'foo...', 'get_gender_display'
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With