Django Rest Framework with ChoiceField Django Rest Framework with ChoiceField django django

Django Rest Framework with ChoiceField


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')


I suggest to use django-models-utils with a custom DRF serializer field

Code becomes:

# models.pyfrom model_utils import Choicesclass User(AbstractUser):    GENDER = Choices(       ('M', 'Male'),       ('F', 'Female'),    )    gender = models.CharField(max_length=1, choices=GENDER, default=GENDER.M)# serializers.py from rest_framework import serializersclass ChoicesField(serializers.Field):    def __init__(self, choices, **kwargs):        self._choices = choices        super(ChoicesField, self).__init__(**kwargs)    def to_representation(self, obj):        return self._choices[obj]    def to_internal_value(self, data):        return getattr(self._choices, data)class UserSerializer(serializers.ModelSerializer):    gender = ChoicesField(choices=User.GENDER)    class Meta:        model = User# viewsets.pyclass UserViewSet(viewsets.ModelViewSet):    queryset = User.objects.all()    serializer_class = UserSerializer


An update for this thread, in the latest versions of DRF there is actually a ChoiceField.

So all you need to do if you want to return the display_name is to subclass ChoiceField to_representation method like this:

from django.contrib.auth import get_user_modelfrom rest_framework import serializersUser = get_user_model()class ChoiceField(serializers.ChoiceField):    def to_representation(self, obj):        if obj == '' and self.allow_blank:            return obj        return self._choices[obj]    def to_internal_value(self, data):        # To support inserts with the value        if data == '' and self.allow_blank:            return ''        for key, val in self._choices.items():            if val == data:                return key        self.fail('invalid_choice', input=data)class UserSerializer(serializers.ModelSerializer):    gender = ChoiceField(choices=User.GENDER_CHOICES)    class Meta:        model = User

So there is no need to change the __init__ method or add any additional package.