Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django Rest Framework Choices Field Serializer

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?

like image 243
Denise Mauldin Avatar asked Sep 14 '25 09:09

Denise Mauldin


2 Answers

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
like image 96
Linovia Avatar answered Sep 16 '25 00:09

Linovia


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'
like image 34
hadi ahadi Avatar answered Sep 16 '25 00:09

hadi ahadi