API Reference
The library exposes two public classes, both importable from the top-level package:
from django_dynamic_serializer import (
DynamicSerializerFieldsMixin,
DynamicSerializerView,
)
DynamicSerializerFieldsMixin
Module: django_dynamic_serializer.mixins
A serializer mixin that accepts an optional fields keyword argument to
dynamically select which fields are included in the serialized output. Add it to
any ModelSerializer (or any Serializer subclass) as the first parent
class so its __init__ runs before the DRF base class.
from rest_framework import serializers
from django_dynamic_serializer import DynamicSerializerFieldsMixin
class AuthorSerializer(DynamicSerializerFieldsMixin, serializers.ModelSerializer):
class Meta:
model = Author
fields = ["id", "name", "birth_year"]
class BookSerializer(DynamicSerializerFieldsMixin, serializers.ModelSerializer):
author = AuthorSerializer()
reviews = ReviewSerializer(many=True)
class Meta:
model = Book
fields = ["id", "title", "isbn", "author", "reviews"]
Field specification format
The fields argument is a list where each entry is either:
Entry type |
Meaning |
|---|---|
|
Include a top-level field as-is. |
|
Include a nested serializer and recursively select its sub-fields. |
Example:
fields = [
"id",
"title",
{
"object_name": "author",
"fields": ["id", "name"],
},
]
Nesting can go as deep as your serializer hierarchy requires:
fields = [
"id",
"name",
{
"object_name": "books",
"fields": [
"id",
"title",
{"object_name": "author", "fields": ["name"]},
],
},
]
How it works
__init__pops thefieldskwarg before callingsuper().__init__()so that DRF’sSerializer.__init__does not receive an unexpected argument.After the parent
__init__has built the fullself.fieldsordered dict,_apply_field_selectionis called to prune it._apply_field_selectionwalks the requested field list. For each nested dict entry it recurses into the child serializer’s.fields. After processing all entries, any field not in the requested set is removed from the serializer.When a field wraps a
many=Trueserializer, DRF represents it as aListSerializer. The method transparently unwraps toListSerializer.childbefore applying the selection.
DynamicSerializerView
Module: django_dynamic_serializer.views
A view mixin that connects the field specification to the serializer. Combine it
with any DRF generic view (ListAPIView, RetrieveAPIView, etc.) as the
first parent class.
from rest_framework.generics import ListAPIView
from django_dynamic_serializer import DynamicSerializerView
class BookListView(DynamicSerializerView, ListAPIView):
serializer_class = BookSerializer
queryset = Book.objects.select_related("author")
def get_serializer_fields(self):
return [
"id",
"title",
{"object_name": "author", "fields": ["id", "name"]},
]
get_serializer_fields()
Subclasses must implement this method. It returns the field specification list
(same format accepted by DynamicSerializerFieldsMixin). If not implemented,
a NotImplementedError is raised at request time.
get_serializer()
Overrides DRF’s get_serializer() to inject the fields kwarg on GET
requests. For non-GET methods (POST, PUT, PATCH, DELETE) the serializer is
created normally with all fields, so write operations are unaffected.
_get_empty_serializer()
Creates a field-filtered serializer instance with instance=None. This hook
exists specifically for the django-virtual-models integration: the
VirtualModelListAPIView calls _get_empty_serializer() to inspect which
fields are present, then generates only the needed prefetch_related calls.
See Integration with django-virtual-models for details.
On non-GET requests this method returns a plain serializer (no field filtering) so that introspection used by virtual models does not interfere with write operations.