django-ninja Notes ¶
Hello world
from ninja import Router v1_router = Router(tags=["cclib"]) @v1_router.get("/hello") def hello(request): return "Hello world!"
A basic example to expose a Django Model
from typing import List import uuid from django.shortcuts import get_object_or_404 from ninja import Router from ninja import Schema, ModelSchema from ninja.security import django_auth from cclib.resources.models import Document v1_router = Router(tags=["cclib"]) class DocumentSchema(ModelSchema): class Meta: model = Document fields = "__all__" @v1_router.get("/documents/{uuid:document_id}", response=DocumentSchema, auth=django_auth) def get_document(request, document_id: uuid.UUID): return get_object_or_404(Document, pk=document_id) @v1_router.get("/documents", response=List[DocumentSchema], auth=django_auth) def list_documents(request): qs = Document.objects.all() return qs
Nested objects
There is also often a need to return responses with some nested/child objects ...
https://django-ninja.dev/guides/response/#nested-objects
See also:
Example:
import traceback from typing import List from ninja import Router from ninja import Schema, ModelSchema from ninja.errors import HttpError from ninja.security import django_auth from ninja.security import django_auth_superuser from django.conf import settings from django.contrib.auth.models import Group from django.contrib.auth import get_user_model v1_router = Router(tags=["ccserver"]) class GroupSchema(ModelSchema): class Meta: model = Group fields = "__all__" class UserSchema(ModelSchema): # See: "Nested objects" # https://django-ninja.dev/guides/response/#nested-objects groups: List[GroupSchema] = [] class Meta: model = get_user_model() #fields = "__all__" fields = [ 'id', 'username', ] @v1_router.get("/users", response=List[UserSchema], auth=django_auth_superuser) def list_users(request): try: User = get_user_model() qs = User.objects.all() except Exception as e: # See: "Throwing HTTP responses with exceptions" # https://django-ninja.dev/guides/errors/#throwing-http-responses-with-exceptions raise HttpError(500, str(e) + "\n" + traceback.format_exc()) return qs
Aliases
Instead of a nested response, you may want to just flatten the response output.
The Ninja Schema object extends Pydantic's Field(..., alias="") format to work with dotted responses.
Authentication
https://django-ninja.dev/guides/authentication/
Examples:
from ninja import NinjaAPI from ninja.security import django_auth api = NinjaAPI(csrf=True) @api.get("/pets", auth=django_auth) def pets(request): return f"Authenticated user {request.auth}"
If you need to authorize only a superuser, you can use from ninja.security import django_auth_superuser instead.
Here's an example where the client, in order to authenticate, needs to pass a header:
Authorization: Bearer supersecret:
from ninja.security import HttpBearer class AuthBearer(HttpBearer): def authenticate(self, request, token): if token == "supersecret": return token @api.get("/bearer", auth=AuthBearer()) def bearer(request): return {"token": request.auth}
Throwing HTTP responses with exceptions
As an alternative to custom exceptions and writing handlers for it - you can as well throw http exception that will lead to returning a http response with desired code
https://django-ninja.dev/guides/errors/#throwing-http-responses-with-exceptions
from ninja.errors import HttpError @api.get("/some/resource") def some_operation(request): if True: raise HttpError(503, "Service Unavailable. Please retry later.")
Best practices
Have separate routers for each domain:
https://django-ninja.dev/guides/routers/
See also the following discussion:
https://www.reddit.com/r/django/comments/13zg8uw/django_ninja_architecture/