Quick Start (Serializer)
Quick Start (Serializer)¶
This guide shows how to create a CRUD API using the Serializer class with plain Django models. This approach keeps your models unchanged and defines API configuration separately.
Alternative Approach
If you prefer an all-in-one approach with embedded serialization, see Quick Start (ModelSerializer).
When to Use Serializer¶
Choose the Serializer approach when:
- You have existing Django models you don't want to modify
- You want to keep models and API concerns separated
- You're adding API functionality to an existing project
- Multiple teams work on models vs. API layers
1. Create Your Model¶
Use a standard Django model:
# models.py
from django.db import models
class Article(models.Model):
title = models.CharField(max_length=200)
content = models.TextField()
is_published = models.BooleanField(default=False)
created_at = models.DateTimeField(auto_now_add=True)
class Meta:
ordering = ["-created_at"]
2. Create Your Serializer¶
Define a Serializer class with API configuration in a nested Meta class:
# serializers.py
from ninja_aio.models import serializers
from .models import Article
class ArticleSerializer(serializers.Serializer):
class Meta:
model = Article
schema_in = serializers.SchemaModelConfig(
fields=["title", "content"],
optionals=[("is_published", bool)],
)
schema_out = serializers.SchemaModelConfig(
fields=["id", "title", "content", "is_published", "created_at"]
)
schema_update = serializers.SchemaModelConfig(
optionals=[
("title", str),
("content", str),
("is_published", bool),
]
)
3. Create Your ViewSet¶
Define your API views using APIViewSet with serializer_class:
# views.py
from ninja_aio import NinjaAIO
from ninja_aio.views import APIViewSet
from .models import Article
from .serializers import ArticleSerializer
api = NinjaAIO(title="My Blog API", version="1.0.0")
@api.viewset(model=Article)
class ArticleViewSet(APIViewSet):
serializer_class = ArticleSerializer
4. Configure URLs¶
Add the API to your URL configuration:
# urls.py
from django.urls import path
from .views import api
urlpatterns = [
path("api/", api.urls),
]
5. Run Your Server¶
Visit http://localhost:8000/api/docs to see your auto-generated API documentation!
Adding Relationships¶
The Serializer approach supports nested serialization for related models:
# models.py
from django.db import models
class Author(models.Model):
name = models.CharField(max_length=200)
email = models.EmailField()
class Article(models.Model):
title = models.CharField(max_length=200)
content = models.TextField()
author = models.ForeignKey(Author, on_delete=models.CASCADE, related_name="articles")
is_published = models.BooleanField(default=False)
created_at = models.DateTimeField(auto_now_add=True)
# serializers.py
from ninja_aio.models import serializers
from .models import Author, Article
class AuthorSerializer(serializers.Serializer):
class Meta:
model = Author
schema_out = serializers.SchemaModelConfig(
fields=["id", "name", "email"]
)
class ArticleSerializer(serializers.Serializer):
class Meta:
model = Article
schema_in = serializers.SchemaModelConfig(
fields=["title", "content", "author"],
)
schema_out = serializers.SchemaModelConfig(
fields=["id", "title", "content", "author", "is_published", "created_at"]
)
schema_update = serializers.SchemaModelConfig(
optionals=[
("title", str),
("content", str),
("is_published", bool),
]
)
# Nested serialization for the author field
relations_serializers = {
"author": AuthorSerializer,
}
class QuerySet:
# Optimize queries with select_related
read = serializers.ModelQuerySetSchema(
select_related=["author"]
)
Adding Lifecycle Hooks¶
Add custom logic to CRUD operations using hooks:
# serializers.py
from ninja_aio.models import serializers
from .models import Article
class ArticleSerializer(serializers.Serializer):
class Meta:
model = Article
schema_in = serializers.SchemaModelConfig(
fields=["title", "content"],
customs=[("notify_subscribers", bool, False)], # Custom field
)
schema_out = serializers.SchemaModelConfig(
fields=["id", "title", "content", "is_published", "created_at"]
)
schema_update = serializers.SchemaModelConfig(
optionals=[("title", str), ("content", str), ("is_published", bool)]
)
async def custom_actions(self, payload, instance):
"""Execute after field assignment, before save."""
if payload.get("notify_subscribers"):
await send_notification(instance.title)
async def post_create(self, instance):
"""Execute after instance creation."""
await AuditLog.objects.acreate(
action="article_created",
article_id=instance.id
)
def before_save(self, instance):
"""Execute before any save (sync hook)."""
instance.slug = slugify(instance.title)
def on_delete(self, instance):
"""Execute after deletion (sync hook)."""
logger.info(f"Article {instance.id} deleted")
Next Steps¶
-
Serializer Configuration
-
APIViewSet Features
-
Authentication
-
Pagination