Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Additional field while serializing django rest framework

I am a newbie to django rest framework and have created a sample Employee model.

My models.py:

class Employees(models.Model):
    created = models.DateTimeField(auto_now_add=True)
    first_name = models.CharField(max_length=100)
    last_name = models.CharField(max_length=100)

My serializers.py:

class EmployeeSerializer(serializers.Serializer):
    class Meta:
        model = Employees
        fields = ('first_name','last_name')

This works fine but I want an additional field full_name, which will be first_name + last_name.

How do I define this new field full_name in my serializers.py?

like image 659
user1050619 Avatar asked Mar 27 '14 02:03

user1050619


People also ask

How do you make a field optional in a serializer?

You could use a SerializerMethodField to either return the field value or None if the field doesn't exist, or you could not use serializers at all and simply write a view that returns the response directly. Update for REST framework 3.0 serializer. fields can be modified on an instantiated serializer.

How do you pass extra context data to Serializers in Django REST framework?

In function based views we can pass extra context to serializer with "context" parameter with a dictionary. To access the extra context data inside the serializer we can simply access it with "self. context". From example, to get "exclude_email_list" we just used code 'exclude_email_list = self.


3 Answers

I see two ways here (I prefer the first way since you can reuse it in other parts of the app):

add a calculated property to your model and add it to your serializer by using a readonly field with source=

# models.py
class Employees(models.Model):
    created = models.DateTimeField(auto_now_add=True)
    first_name = models.CharField(max_length=100)
    last_name = models.CharField(max_length=100)

    @property
    def full_name(self):
        return self.first_name + self.last_name

# serializers.py
class EmployeeSerializer(serializers.ModelSerializer):
    full_name = serializers.Field(source='full_name')

    class Meta:
        model = Employees
        fields = ('first_name','last_name', 'full_name')

by using SerializerMethodField (your model unchanged)

class EmployeeSerializer(serializers.ModelSerializer):
    full_name = serializers.SerializerMethodField('get_full_name')

    def get_full_name(self, obj):
        return obj.first_name + obj.last_name

    class Meta:
        model = Employees
        fields = ('first_name','last_name', 'full_name')
like image 169
Denis Cornehl Avatar answered Oct 27 '22 21:10

Denis Cornehl


Provided that the Employee is a login user, then most of us will use django.auth.User, I will share how Employee can be implemented as another Profile (extension of django User). Also with the addition of full_name.read_only, first_name.write_only, and last_name.write_only

# models.py
class Employee(models.Model):
    """User Profile Model"""
    user = models.OneToOneField('auth.User')

# serializers.py
class EmployeeSerializer(serializers.HyperlinkedModelSerializer):
    username = serializers.CharField(source='user.username')
    email = serializers.EmailField(source='user.email')

    first_name = serializers.CharField(
            source='user.first_name', write_only=True)
    last_name = serializers.CharField(
            source='user.last_name', write_only=True)
    name = serializers.CharField(
            source='user.get_full_name', read_only=True)


    class Meta:
        model = Employee
        fields = (
            'url', 'username', 'email',
            'first_name', 'last_name', 'name')
        depth = 1
like image 34
Yeo Avatar answered Oct 27 '22 21:10

Yeo


SerializerMethodField works fine, and we can also store data in serializer object and let method get_field_name use that.

Example:

class MySerializer(serializers.ModelSerializer):
    statistic = serializers.SerializerMethodField()

    def __init__(self, instance=None, data=serializers.empty, statistic=None, **kwargs):
        super(MySerializer, self).__init__(instance=instance, data=data, **kwargs)
        self.statistic = statistic

    def get_statistic(self, obj):
        if self.statistic is None:
            return serializers.empty
        return self.statistic.get(obj.id, {})
like image 4
Craynic Cai Avatar answered Oct 27 '22 20:10

Craynic Cai