A serializer defines the shape of data crossing an API boundary. In Django Ninja, a ModelSchema can turn a model object into a JSON-ready response, while a separate schema can describe the JSON payload accepted to create an object. Keeping input and output serializers separate avoids pretending a new object already has fields, such as an ID, that only exist after creation. section 11.2.2 section 11.2.6
Start with the model fields the API should expose, then add computed fields when they help API consumers. A venue response includes its ID, name, and description, plus a slug made from its name and ID and a URL that points to its detail endpoint. The serializer’s resolver methods calculate those extra values rather than requiring matching fields on the Venue model. section 11.2.2
Listing 11.7 API endpoint for fetching a Venue object
# RiffMates/bands/api.py
from django.shortcuts import get_object_or_404
from django.urls import reverse
from django.utils.text import slugify
from ninja import Router, ModelSchema
from bands.models import Venue
router = Router() #1
class VenueOut(ModelSchema):
slug: str #2
url: str
class Meta:
model = Venue
fields = ["id", "name", "description"] #3
@staticmethod
def resolve_slug(obj): #4
slug = slugify(obj.name) + "-" + str(obj.id)
return slug
@staticmethod
def resolve_url(obj): #5
url = reverse("api-1.0:fetch_venue", args=[obj.id, ])
return url
@router.get("/venue/{venue_id}/",
response=VenueOut,
url_name="fetch_venue") #6
def fetch_venue(request, venue_id):
venue = get_object_or_404(Venue, id=venue_id)
return venue
This endpoint returns a Venue object, while VenueOut selects model fields and resolves a slug and detail URL for the response. section 11.2.2
A practical serializer design separates several jobs:
- Select response fields with a ModelSchema Meta class, rather than automatically exposing every model field. section 11.2.2
- Add declared fields and resolve them with methods when the API representation needs computed values such as a slug or URL. section 11.2.2
- Use a dedicated input schema for POST data; its .dict() result can supply keyword arguments to the model constructor. section 11.2.6
- Nest a related-object serializer when one response should include associated data, reducing repeated API calls. section 11.2.4
Nested serializers let an API return related data in one representation. A RoomSchema supplies each room’s ID and name; VenueOut declares a list of those schemas. Django’s related manager is named room_set, but an alias exposes the clearer API field name rooms. That small rename keeps Django conventions from leaking into a public response. section 11.2.4
Venue input and output
A client POSTs JSON containing a venue name and description. Ninja validates it as VenueIn, .dict() produces the constructor values, and the endpoint creates the Venue. The response uses VenueOut instead, returning the newly assigned ID alongside the name, description, computed slug, URL, and, when configured, nested rooms. section 11.2.2 section 11.2.4 section 11.2.6



