Django REST Polymorphic
django-rest-polymorphic is a Python library that provides polymorphic serializers for Django REST Framework. It enables you to easily define serializers for models that utilize inheritance through the django-polymorphic library. The current version is 0.1.10, and while its core functionality has been integrated into django-polymorphic, the standalone package is still available on PyPI.
Warnings
- breaking The core `PolymorphicSerializer` functionality has been incorporated directly into `django-polymorphic` (specifically at `polymorphic.contrib.drf.serializers.PolymorphicSerializer`). While `django-rest-polymorphic` still exists, the recommended approach for new projects or migrating existing ones is to switch imports.
- gotcha When extending `HyperlinkedModelSerializer` instead of `ModelSerializer`, you need to explicitly define `extra_kwargs` to direct the URL to the appropriate view for your polymorphic serializer. This ensures correct URL generation for specific child types.
- gotcha By default, the polymorphic type is identified by a field named `resource_type`. If you need to use a different field name in your API requests/responses, you must override the `resource_type_field_name` attribute.
- gotcha Using `django-polymorphic` (and consequently `django-rest-polymorphic`) for model inheritance can have performance implications. Each query to a base polymorphic model will result in `INNER JOIN` operations to fetch fields from subclassed models.
Install
-
pip install django-rest-polymorphic
Imports
- PolymorphicSerializer
from rest_polymorphic.serializers import PolymorphicSerializer
Quickstart
from django.db import models
from rest_framework import serializers, viewsets
from polymorphic.models import PolymorphicModel
from rest_polymorphic.serializers import PolymorphicSerializer
# 1. Define polymorphic models using django-polymorphic
class Project(PolymorphicModel):
topic = models.CharField(max_length=30)
class ArtProject(Project):
artist = models.CharField(max_length=30)
class ResearchProject(Project):
supervisor = models.CharField(max_length=30)
# 2. Define serializers for each concrete model
class ProjectSerializer(serializers.ModelSerializer):
class Meta:
model = Project
fields = ('topic', 'resource_type') # 'resource_type' is added automatically by PolymorphicSerializer
class ArtProjectSerializer(serializers.ModelSerializer):
class Meta:
model = ArtProject
fields = ('topic', 'artist', 'resource_type')
class ResearchProjectSerializer(serializers.ModelSerializer):
class Meta:
model = ResearchProject
fields = ('topic', 'supervisor', 'resource_type')
# 3. Create a PolymorphicSerializer to map models to serializers
class ProjectPolymorphicSerializer(PolymorphicSerializer):
model_serializer_mapping = {
Project: ProjectSerializer,
ArtProject: ArtProjectSerializer,
ResearchProject: ResearchProjectSerializer
}
# 4. Use the polymorphic serializer in a ViewSet
class ProjectViewSet(viewsets.ModelViewSet):
queryset = Project.objects.all()
serializer_class = ProjectPolymorphicSerializer