78

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?

3 Answers 3

126

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')
Sign up to request clarification or add additional context in comments.

4 Comments

For me, using serializers.Field gave an error. serializers.ReadOnlyField does work if to_representation is not defined and the view is read-only.
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)
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.
Note: full_name = serializers.SerializerMethodField() will automatically resolve to def get_full_name(self, obj):. Only specify the method name if it doesn't follow the naming style: get_${field_name}
7

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

Comments

5

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, {})

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.