Manu Artero
Manu Artero

Reputation: 10303

Django Rest Framework: serializer for two models that inherit from a common base abstract model

There is an abstract model that defines an interface for two child models. I've been asked to create an API endpoint that will return instances from those child models (including only the common fields defined thanks to the interface father class).

The problem raises when defining the Serializer.Meta.model attribute.

Anyway, code is always clearer:

models.py

class Children(Model):
    class Meta:
        abstract = True

    def get_foo(self):
        raise NotImplementedError

class Daughter(Children):
    def get_foo(self):
        return self.xx

class Son(Children):
    def get_foo(self):
        return self.yy

api/views.py

class ChildrenApiView(ListAPIView):
    serializer_class = ChildrenSerializer

    def get_queryset(self):
        daughters = Daughter.objects.all()
        sons = Son.objects.all()
        return list(daughters) + list(sons)

serializers.py

class ChildrenSerializer(ModelSerializer):
    foo = CharField(source="get_foo", read_only=True)

    class Meta:
      model = Children  # <========= HERE IS THE PROBLEM
      fields = ('foo',)

Some thoughts;

  1. I know I'm not able to point out to the abstract model Children (wrote it for showing the inntention)
  2. I tried to leave ChildrenSerializer.Meta.model empty
  3. Seems that I can choose whichever Daughter or Son but not sure if that solution has any side-effect or is the way to go.
  4. Tried to create DaughterSerializer & SonSerializer and use the method get_serializer_class(self) at the view, but wasn't able to make it run

Upvotes: 0

Views: 433

Answers (1)

I would probabaly not have a model serializer, and instead have a standard Serializer, with all the fields that you want to return in the view.

This will make it applicable for both Son and Daughter.

So the serializer would be something like:

class ChildrenSerializer(serializers.Serializer):
    foo = CharField(source="get_foo", read_only=True)

Upvotes: 1

Related Questions