Additional field while serializing django rest framework

24,688

Solution 1

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

Solution 2

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

Solution 3

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, {})
Share:
24,688
user1050619
Author by

user1050619

Updated on July 08, 2022

Comments

  • user1050619
    user1050619 almost 2 years

    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?

  • Anatoly Scherbakov
    Anatoly Scherbakov almost 9 years
    For me, using serializers.Field gave an error. serializers.ReadOnlyField does work if to_representation is not defined and the view is read-only.
  • Pynchia
    Pynchia over 8 years
    I have just had the same problem (I am not serializing a Django model, but another plain class) and after having banged my head on it for a while I found out that it works fine if you use full_name = serializers.ReadOnlyField(), i.e. discarding the source parameter altogether. As the documentation says about the source parameter: it defaults to the name of the field. Ans it works even if it's a method (or a property)
  • blueFast
    blueFast almost 6 years
    For me (django 1.11.13) there is no need to declare the field in the serializer, just declare it in the Model and list it in the Meta.fields.