Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Returning the human-readable element of a Choice Field in DRF serializer

How do I return the human readable element of a Choice field in a Serializer Class. Sample code below.

from rest_framework import serializers  
from model_utils import Choices
from django.utils.translation import ugettext_lazy as _

COMPANY_TYPE = Choices(
    (1, 'Public', _('Public Company')),
    (2, 'Private', _('Private Company')),
    (3, 'Other', _('Other Type')),
)

class CompanySerializer(serializers.ModelSerializer):
    company_type = serializers.ChoiceField(choices=COMPANY_TYPE)
    company_type_name = serializers.ReadOnlyField(source=COMPANY_TYPE[1])   # <=== This is the issue

    class Meta:
        model = Company
        fields = ('id', 'title', 'company_type', 'company_type_name')

If say an entry in the company table has company_type = 1, and a user makes an API request, I want to include the extra field of company_type_name with the value Public Company.

So the issue is am unable to pass the current value of company_type to the serializer so that it can return the String value of the Choice Field.

like image 655
lukik Avatar asked Mar 21 '18 19:03

lukik


People also ask

What does serializer data return?

The BaseSerializer class caches its data attribute on the object, but Serializer. data returns a copy of BaseSerializer. data every time it is accessed (via ReturnDict ). This is a little inefficient (which is not a big deal), but it means that any changes to the data dict will essentially be reset when Serializer.

What does serializer Is_valid do?

The .is_valid() method takes an optional raise_exception flag that will cause it to raise a serializers.ValidationError exception if there are validation errors.

What is HyperlinkedModelSerializer?

HyperlinkedModelSerializer is a layer of abstraction over the default serializer that allows to quickly create a serializer for a model in Django. Django REST Framework is a wrapper over default Django Framework, basically used to create APIs of various kinds.

What does a serializer return Django?

Serializers in Django REST Framework are responsible for converting objects into data types understandable by javascript and front-end frameworks. Serializers also provide deserialization, allowing parsed data to be converted back into complex types, after first validating the incoming data.


2 Answers

You can do it with method field and by get_Foo_dispay()

company_type_name = serializers.SerializerMethodField()
def get_company_type_name(self, obj):
    return obj.get_company_type_display()
like image 66
Sachin G. Avatar answered Oct 21 '22 10:10

Sachin G.


From the DRF Oficial DC the choices must be a list of valid values, or a list of (key, display_name) tuples
So your choices must be in following format,

COMPANY_TYPE = (
    (1, 'Public'),
    (2, 'Private'),
    (3, 'Other'),
)

NB : model_utils.Choices does the same thing

I think you need a SerializerMethodField with read_only=True rather than a ReadOnlyField. So Change your serializer as below,

class CompanySerializer(serializers.ModelSerializer):
    def get_company_type_name(self, obj):
        return COMPANY_TYPE.__dict__.get('_display_map').get(obj['company_type'])

    company_type = serializers.ChoiceField(choices=COMPANY_TYPE)
    company_type_name = serializers.SerializerMethodField(read_only=True, source='get_company_type_name')

    class Meta:
        model = Company
        fields = ('id', 'title', 'company_type', 'company_type_name')


like image 25
JPG Avatar answered Oct 21 '22 09:10

JPG