user4829254
user4829254

Reputation:

Django REST Framework - SerializerMethodField is null on serializer.save()

I am using Django and REST Framework. I want to save with serializer by data. I called to serializer.save(). But saved model field is null with animal field in HumanSerializer. I want define animal field by SerializerMethodField and want to save model. How to do it?

Serializer:

class HumanSerializer(serializers.ModelSerializer):

    animal = SerializerMethodField()

    class Meta:
        model = Human
        fields = (
            'id',
            'animal', # <- animal is ForeignKey of Animal model
        )

    def get_animal(self, lead):
        # blah blah blah
        pass

A save process:

data['animal'] = 1
serializer = HumanSerializer(
    data=data,
    context={'request': request},
)
if serializer.is_valid():
    human = serializer.save()
    human.animal # <- animal is null. but delete SerializerMethodField then not null

Upvotes: 5

Views: 3145

Answers (3)

Ken4scholars
Ken4scholars

Reputation: 6296

First, a SerializerMethodField is read only by design. So you cannot use it to accept the Human data. Secondly, creation of nested objects cannot be handled by the serializer by default. You have the override the create method and handle the creation of the nested objects. Check the docs on how to implement writable nested serializers

Upvotes: 1

satyam verma
satyam verma

Reputation: 46

SerializerMethodField is read only by default. So when your serializer will validate data, it will chuck out 'animal' key from data for saving into models.

To overcome this, one way is to override serializer's validate function so that it will not remove animal key from your data. Example:

class HumanSerializer(serializers.ModelSerializer):


    animal = SerializerMethodField()


    def validate(self, data):
        animal = data['animal']
        # Any validation code for animal, if required
        validated_data = super(HumanSerializer, self).validate(data)
        validated_data['animal'] = animal
        return validated_data


    class Meta:
        model = Human
        fields = (
            'id',
            'animal',  # <- animal is ForeignKey of Animal model
        )


    def get_animal(self, lead):
        # blah blah blah
        pass

Upvotes: 0

Sachin
Sachin

Reputation: 3664

SerializerMethodField is always a read only field. You can add another field for the writing purposes.

Example:

class HumanSerializer(serializers.ModelSerializer):

    animal = SerializerMethodField()
    animal_id = serializers.PrimaryKeyRelatedField(
        source='animal',
        queryset=Animal.objects.all(),
        write_only=True
    )

    class Meta:
        model = Human
        fields = (
            'id',
            'animal',
            'animal_id'
        )

Then, pass animal_id in the request data to save the Animal along with the Human.

Ref:
* PrimaryKeyRelatedField docs

Upvotes: 3

Related Questions