Skip to content
Back to top
View this page
Edit this page

# djangorestframework

Polymorphic serializers for Django REST Framework.

The django-rest-polymorphic package has been incorporated into django-polymorphic. This contrib package allows you to easily define serializers for your inherited models that you have created using `django-polymorphic` library. To migrate from django-rest-polymorphic, you need to change your import paths from `rest_polymorphic.serializers` to `polymorphic.contrib.drf.serializers`.

## Usage

Define your polymorphic models:

     1from django.db import models
     2
     3from polymorphic.models import PolymorphicModel
     4
     5
     6class Project(PolymorphicModel):
     7    topic = models.CharField(max_length=30)
     8
     9
    10class ArtProject(Project):
    11    artist = models.CharField(max_length=30)
    12
    13
    14class ResearchProject(Project):
    15    supervisor = models.CharField(max_length=30)

Define serializers for each polymorphic model the way you did it when you used djangorestframework:

     1from rest_framework import serializers
     2
     3from polymorphic.contrib.drf.serializers import PolymorphicSerializer
     4
     5from .models import Project, ArtProject, ResearchProject
     6
     7
     8class ProjectSerializer(serializers.ModelSerializer):
     9    class Meta:
    10        model = Project
    11        fields = ("topic",)
    12
    13
    14class ArtProjectSerializer(serializers.ModelSerializer):
    15    class Meta:
    16        model = ArtProject
    17        fields = ("topic", "artist", "url")
    18        extra_kwargs = {
    19            "url": {"view_name": "drf:project-detail", "lookup_field": "pk"},
    20        }
    21
    22
    23class ResearchProjectSerializer(serializers.ModelSerializer):
    24    class Meta:
    25        model = ResearchProject
    26        fields = ("topic", "supervisor")

Note that if you extend HyperlinkedModelSerializer instead of ModelSerializer you need to define extra_kwargs to direct the URL to the appropriate view for your polymorphic serializer.

Then you have to create a polymorphic serializer that serves as a mapper between models and serializers which you have defined above:

    class ProjectPolymorphicSerializer(PolymorphicSerializer):
        model_serializer_mapping = {
            Project: ProjectSerializer,
            ArtProject: ArtProjectSerializer,
            ResearchProject: ResearchProjectSerializer,
        }

Create viewset with serializer_class equals to your polymorphic serializer:

    1from rest_framework import viewsets
    2
    3from .models import Project
    4from .example_serializers import ProjectPolymorphicSerializer
    5
    6
    7class ProjectViewSet(viewsets.ModelViewSet):
    8    queryset = Project.objects.all()
    9    serializer_class = ProjectPolymorphicSerializer

Test it:

    $ http GET "http://localhost:8000/projects/"

    HTTP/1.0 200 OK
    Content-Length: 227
    Content-Type: application/json

    [
        {
            "resourcetype": "Project",
            "topic": "John's gathering"
        },
        {
            "artist": "T. Turner",
            "resourcetype": "ArtProject",
            "topic": "Sculpting with Tim",
            "url": "http://localhost:8000/projects/2/"
        },
        {
            "resourcetype": "ResearchProject",
            "supervisor": "Dr. Winter",
            "topic": "Swallow Aerodynamics"
        }
    ]

    $ http POST "http://localhost:8000/projects/" resourcetype="ArtProject" topic="Guernica" artist="Picasso"

    HTTP/1.0 201 Created
    Content-Length: 67
    Content-Type: application/json

    {
        "artist": "Picasso",
        "resourcetype": "ArtProject",
        "topic": "Guernica",
        "url": "http://localhost:8000/projects/4/"
    }

## Customize resource type

As you can see from the example above, in order to specify the type of your polymorphic model, you need to send a request with resource type field. The value of resource type should be the name of the model.

If you want to change the resource type field name from `resourcetype` to something else, you should override `resource_type_field_name` attribute:

    class ProjectPolymorphicSerializer(PolymorphicSerializer):
        resource_type_field_name = 'projecttype'
        ...

If you want to change the behavior of resource type, you should override `to_resource_type` method:

    class ProjectPolymorphicSerializer(PolymorphicSerializer):
        ...

        def to_resource_type(self, model_or_instance):
            return model_or_instance._meta.object_name.lower()

Now, the request for creating new object will look like this:

    $ http POST "http://localhost:8000/projects/" projecttype="artproject" topic="Guernica" artist="Picasso"