Search code examples
djangodjango-rest-frameworkdjango-rest-viewsets

Serializer for inherited model


I have following models declared:

class Parent(models.Model):
    active = models.BooleanField(default=False)

class Child(Parent)
    name = models.CharField(max_length=100, unique=True)

and serializer:

class ChildSerializer(serializers.ModelSerializer):

    class Meta:
        model = Child
        fields = ('active', 'name')

At glance everything seems to be ok, it's correctly generated in the browsable api. Neverthless when I want to update both fields only 'active' is updated.

When I do put in return I receive correct resonse:

{
  "active": true,
  "name": "foo"
}

But the name field is not updated at all. I went further and tried to implemented custom update method in the serializer:

def update(self, instance, validated_data):
    print(str(type(instance)))
    return instance

After that in a put response I'm receiving only active field ?:

{
  "active": true,
}

And on console even more astonishing:

rest_1  | <class 'applic.models.Person'>

I'm completely lost :) Why on earth serializer treats explicitly provided Child model as a Person ? How to force ChildSerializer to work on Child model ?

Thank you in advance Piotr


Solution

  • Change your models.py as below,

    class Parent(models.Model):
        active = models.BooleanField(default=False)
    
    
    class Child(Parent):
        parent = models.OneToOneField(Parent)
        name = models.CharField(max_length=100, unique=True)
    


    and try ModelViewSet in views.py as below,

    class YourViewClass(ModelViewSet):
        serializer_class = ChildSerializer
        queryset = Child.objects.all()
    


    Assuming your api end-point is /api/vi/sample/, then

    to add instance, use POST method on /api/vi/sample/ payload will be as below

    {
        "active": true,
        "name": "name_choice"
    }
    



    to edit instance, PUT or PATCH on /api/vi/sample/instance_id where instance_id is an integer representing the primary key of the Child instance (example :/api/vi/sample/1 ). Updated payload as below,

    {
        "active": false,
        "name": "name_choice_new_change"
    }
    


    If you'd like to see the instance_id, update your serializer as follows,

    class ChildSerializer(serializers.ModelSerializer):
        class Meta:
            model = Child
            fields = ('id', 'active', 'name')