Write nested serializer with GenericRelation()

239 views Asked by At

I have the following code in which in one of the models I am using a polymorphic model with the django ContentType framework.

models.py

from django.db import models
from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.fields import GenericRelation

# Create your models here.

class LastName(models.Model):
    last_name = models.CharField(max_length=100)
    content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
    object_id = models.PositiveIntegerField()
    content_object = GenericForeignKey()

    def __str__(self):
        return self.last_name

class Person(models.Model):

    first_name = models.CharField(max_length=100)
    last_name = GenericRelation(LastName)
    def __str__(self):
        return self.first_name

serializers.py

from django.db import models
from rest_framework import serializers
from .models import Person, LastName
from django.contrib.contenttypes.models import ContentType

class LastNameSerializer(serializers.ModelSerializer):
    
    class Meta:
        model = LastName
        fields = '__all__'

class PersonSerializer(serializers.ModelSerializer):
    last_name = LastNameSerializer(required=False, many=True)
    class Meta:
        model = Person
        fields = ['id','first_name', 'last_name']
    

    def create(self, validate_data):
        last_names = validate_data.pop('last_name')

        person = Person.objects.create(**validate_data)
     
        for l_name in last_names:
            model = self.Meta.model
            # content_object represents content_type and object_id
            names = LastName(content_object=person, **l_name)
            names.save()
            person.last_name.add(names.id)
        person.save()
        return person

In the serializer.py I am trying to create query to add more than one dictionary with more than one last_name as the create() method above as same as if you added a non-polymorphic serializer.

The payload I am trying to send to the Person endpoint is as follow:

Post:

{
    "first_name": "Oliveira",
    "last_name": [
{"last_name":"Prado"},
{"last_name":"Moreira"},
]
}

Output:

{
    "last_name": [
        {
            "object_id": [
                "This field is required."
            ],
            "content_type": [
                "This field is required."
            ]
        }
    ]
}

The output is obvious but I dont know how to pass the content_type and object_id in the create() method?

I am following this query to create an writable nested serializer using normal query:

>>> from poly_example.models import Person, LastName
>>> 
>>> person = Person(first_name="Oliver")
>>> person.save()
>>> 
>>> last_name = LastName(content_object=person, last_name="Prado")
>>> last_name.save()
>>> 
>>> person
<Person: Oliver>

Like this I am able to create a nested serializer:

    {
        "id": 3,
        "first_name": "Oliver",
        "last_name": [
            {
                "id": 1,
                "last_name": "Prado",
                "object_id": 3,
                "content_type": 7
            }
        ]
    }

but I dont know how to pass this approach into the create() method in the PersonSerializer.

0

There are 0 answers