🥷 Django Ninja Aio CRUD¶
Django Ninja Aio CRUD is a powerful async REST framework built on top of Django Ninja. It provides automatic CRUD operations, class-based views, and built-in utilities to make API development faster and cleaner.
✨ Key Features¶
- 🚀 Fully Async - Built for Django's async ORM
 - 🔄 Automatic CRUD - Generate complete REST APIs with minimal code
 - 📝 ModelSerializer - Define schemas directly on models
 - 🎯 Class-Based Views - Clean, organized view architecture
 - 🔐 JWT Authentication - Built-in async JWT bearer authentication
 - 📄 Auto Documentation - OpenAPI/Swagger UI out of the box
 - 🔗 Relationship Support - Automatic nested serialization (FK, M2M, reverse relations)
 - 📊 Pagination - Built-in async pagination support
 - ⚡ Performance - Using 
orjsonfor fast JSON serialization 
🎯 Why Django Ninja Aio CRUD?¶
Traditional Django REST development requires: - Separate serializer classes - Manual CRUD view implementation - Repetitive boilerplate code - Complex relationship handling
Django Ninja Aio CRUD eliminates this complexity:
# schema.py
class UserSchemaOut(ModelSchema):
    class Meta:
        model = User
        fields = ['id', 'username', 'email']
class UserSchemaIn(ModelSchema):
    class Meta:
        model = User
        fields = ['username', 'email', 'password']
# views.py
@api.get("users", response={200: UserSchemaOut})
async def list_users(request):
    return [user async for user in User.objects.all()]
@api.post("users/", response{201: UserSchemaOut})
async def create_user(request, data: UserSchemaIn):
    user_pk = (await User.objects.acreate(**data.model_dump())).pk
    return 201, await User.objects.aget(pk=pk)
# ... more views for retrieve, update, delete
# models.py
class User(ModelSerializer):
    username = models.CharField(max_length=150)
    email = models.EmailField()
    password = models.CharField(max_length=128)
    class ReadSerializer:
        fields = ["id", "username", "email"]
    class CreateSerializer:
        fields = ["username", "email", "password"]
    class UpdateSerializer:
        optionals = [("email", str)]
# views.py
class UserViewSet(APIViewSet):
    model = User
    api = api
UserViewSet().add_views_to_route()
# Done! List, Create, Retrieve, Update, Delete endpoints ready
📚 Documentation¶
Explore detailed documentation for each component:
Models¶
- Model Serializer - Schema generation and serialization
 - Model Util - Async CRUD utilities
 
Views¶
- API View - Simple custom views
 - API View Set - Complete CRUD operations
 
Advanced Topics¶
- Authentication - JWT and custom auth
 - Pagination - Customize pagination behavior
 
💡 Example: Complete Blog API¶
Here's a real-world example with relationships:
# models.py
from django.db import models
from ninja_aio.models import ModelSerializer
class Author(ModelSerializer):
    name = models.CharField(max_length=200)
    email = models.EmailField(unique=True)
    bio = models.TextField(blank=True)
    class ReadSerializer:
        fields = ["id", "name", "email", "bio", "articles"]
    class CreateSerializer:
        fields = ["name", "email"]
        optionals = [("bio", str)]
class Category(ModelSerializer):
    name = models.CharField(max_length=100)
    slug = models.SlugField(unique=True)
    class ReadSerializer:
        fields = ["id", "name", "slug"]
    class CreateSerializer:
        fields = ["name", "slug"]
class Article(ModelSerializer):
    title = models.CharField(max_length=200)
    slug = models.SlugField(unique=True)
    content = models.TextField()
    author = models.ForeignKey(Author, on_delete=models.CASCADE, related_name="articles")
    category = models.ForeignKey(Category, on_delete=models.SET_NULL, null=True)
    tags = models.ManyToManyField('Tag', related_name="articles")
    is_published = models.BooleanField(default=False)
    views = models.IntegerField(default=0)
    created_at = models.DateTimeField(auto_now_add=True)
    class ReadSerializer:
        fields = [
            "id", "title", "slug", "content",
            "author", "category", "tags",
            "is_published", "views", "created_at"
        ]
    class CreateSerializer:
        fields = ["title", "slug", "content", "author", "category"]
        customs = [("notify_subscribers", bool, True)]
    class UpdateSerializer:
        optionals = [
            ("title", str),
            ("content", str),
            ("is_published", bool),
        ]
    async def custom_actions(self, payload: dict):
        if payload.get("notify_subscribers"):
            # Send notifications
            await notify_new_article(self)
class Tag(ModelSerializer):
    name = models.CharField(max_length=50, unique=True)
    class ReadSerializer:
        fields = ["id", "name"]
# views.py
from ninja_aio import NinjaAIO
from ninja_aio.views import APIViewSet
from .models import Author, Category, Article, Tag
api = NinjaAIO(title="Blog API", version="1.0.0")
class AuthorViewSet(APIViewSet):
    model = Author
    api = api
class CategoryViewSet(APIViewSet):
    model = Category
    api = api
class ArticleViewSet(APIViewSet):
    model = Article
    api = api
    query_params = {
        "is_published": (bool, None),
        "category": (int, None),
        "author": (int, None),
    }
    async def query_params_handler(self, queryset, filters):
        if filters.get("is_published") is not None:
            queryset = queryset.filter(is_published=filters["is_published"])
        if filters.get("category"):
            queryset = queryset.filter(category_id=filters["category"])
        if filters.get("author"):
            queryset = queryset.filter(author_id=filters["author"])
        return queryset
class TagViewSet(APIViewSet):
    model = Tag
    api = api
# Register all views
AuthorViewSet().add_views_to_route()
CategoryViewSet().add_views_to_route()
ArticleViewSet().add_views_to_route()
TagViewSet().add_views_to_route()
This creates a complete blog API with: - 4 models with relationships - Automatic nested serialization - Query filtering - Custom actions - Full CRUD operations for all models
🌟 Key Concepts¶
ModelSerializer¶
Central to Django Ninja Aio CRUD - defines schemas directly on models:
class User(ModelSerializer):
    username = models.CharField(max_length=150)
    class ReadSerializer:
        fields = ["id", "username"]  # Response schema
    class CreateSerializer:
        fields = ["username"]  # Input schema
    class UpdateSerializer:
        optionals = [("username", str)]  # Partial update schema
APIViewSet¶
Automatically generates complete CRUD endpoints:
class UserViewSet(APIViewSet):
    model = User
    api = api
    # Generates: List, Create, Retrieve, Update, Delete
Custom Views¶
Extend with custom endpoints:
class UserViewSet(APIViewSet):
    model = User
    api = api
    def views(self):
        @self.router.post("/{pk}/activate/")
        async def activate(request, pk: int):
            user = await User.objects.aget(pk=pk)
            user.is_active = True
            await user.asave()
            return {"message": "User activated"}
📄 License¶
This project is licensed under the MIT License - see the LICENSE file for details.
☕ Support¶
If you find Django Ninja Aio CRUD useful, consider supporting the project:
🔗 Links¶
- Documentation: https://django-ninja-aio.com
 - GitHub: https://github.com/caspel26/django-ninja-aio-crud
 - PyPI: https://pypi.org/project/django-ninja-aio-crud/
 - Django Ninja: https://django-ninja.dev/
 
Built with ❤️ using Django Ninja