Skip to main content

Nested Serializers

You can use nested DRF serializers to display and edit nested objects in the form view. Nested serializers will be automatically saved and updated when the parent object is created or updated. Be careful with nested serializers: you must use ModelSerializer or AdminModelSerializer (from habarico library) as a base class for your serializers. For M2M nesting, it is required to use Meta inheritance.

from habarico import ModelAdmin
from habarico.serializers import AdminModelSerializer, ModelSerializer
from habarico.schema.generators import EditViewSchemaGenerator
from habarico.schema.boxes import Box, ObjectBox

from .models import Product, Category


class CategorySerializer(ModelSerializer):
"""Nested serializer for category data."""

class Meta(ModelSerializer.Meta): # Don't forget to inherit from ModelSerializer.Meta
model = Category
fields = ["name", "email", "description"]


class ProductSerializer(AdminModelSerializer):
"""Product serializer with nested category."""
category_details = CategorySerializer(source="category", allow_null=True) # Nested category data


class ProductAdmin(ModelAdmin):
model = Product
fields = ["id", "name", "description", "category_details"]
base_serializer_class = ProductSerializer
view_schema_generators = [
EditViewSchemaGenerator(box=Box(
boxes=[
Box(
label="Product",
boxes=["name", "description"],
),
ObjectBox(
label="Category Information",
boxes=["name", "email", "description"],
target="category_details",
),
]
))
]

For many-to-many or reverse relations you can use ArrayBox:

from habarico import ModelAdmin
from habarico.serializers import AdminModelSerializer, ModelSerializer
from habarico.schema.generators import EditViewSchemaGenerator
from habarico.schema.boxes import Box, ArrayBox

from .models import Product, Tag


class TagSerializer(ModelSerializer):
"""Nested serializer for tags."""

class Meta(ModelSerializer.Meta): # Don't forget to inherit from ModelSerializer.Meta
model = Tag
fields = ["pk", "name"] # Include pk field to be able to update tags; without it, tags will be created every time


class ProductSerializer(AdminModelSerializer):
"""Product serializer with nested tags."""
tags = TagSerializer(many=True) # Tags will be saved with the product


class ProductAdmin(ModelAdmin):
model = Product
fields = ["id", "name", "description", "tags"]
base_serializer_class = ProductSerializer
view_schema_generators = [
EditViewSchemaGenerator(box=Box(
boxes=[
Box(
label="Product",
boxes=["name", "description"],
),
ArrayBox(
label="Tags",
boxes=["name"],
target="tags",
),
]
))
]