Django Rest Framework with ChoiceField

awwester picture awwester · Mar 9, 2015 · Viewed 55.8k times · Source

I have a few fields in my user model that are choice fields and am trying to figure out how to best implement that into Django Rest Framework.

Below is some simplified code to show what I'm doing.

# models.py
class User(AbstractUser):
    GENDER_CHOICES = (
        ('M', 'Male'),
        ('F', 'Female'),
    )

    gender = models.CharField(max_length=1, choices=GENDER_CHOICES)


# serializers.py 
class UserSerializer(serializers.ModelSerializer):
    gender = serializers.CharField(source='get_gender_display')

    class Meta:
        model = User


# viewsets.py
class UserViewSet(viewsets.ModelViewSet):
    queryset = User.objects.all()
    serializer_class = UserSerializer

Essentially what I'm trying to do is to have the get/post/put methods use the display value of the choice field instead of the code, looking something like the below JSON.

{
  'username': 'newtestuser',
  'email': '[email protected]',
  'first_name': 'first',
  'last_name': 'last',
  'gender': 'Male'
  // instead of 'gender': 'M'
}

How would I go about doing that? The above code does not work. Before I had something like this working for GET, but for POST/PUT it was giving me errors. I'm looking for general advice on how to do this, it seems like it would be something common, but I can't find examples. Either that or I'm doing something terribly wrong.

Answer

levi picture levi · Mar 10, 2015

Django provides the Model.get_FOO_display method to get the "human-readable" value of a field:

class UserSerializer(serializers.ModelSerializer):
    gender = serializers.SerializerMethodField()

    class Meta:
        model = User

    def get_gender(self,obj):
        return obj.get_gender_display()

for the latest DRF (3.6.3) - easiest method is:

gender = serializers.CharField(source='get_gender_display')