Django Ninja Documentation

repository·master·Indexed 27 days ago

https://github.com/vitalik/django-ninja

A high-performance web framework for building APIs with Django using Python 3.6+ type hints and Pydantic for data validation. It supports async operations, integrates with ASGI servers like Uvicorn and Daphne, and provides built-in support for Swagger UI and Redoc. Features include flexible authentication (API keys, session-based, and custom callables), async ORM integration for Django 4.1+, and configurable decorator modes for request lifecycle management.

Tokens
32.5K
Snippets
123
Records
179
Agent score
94%

What's inside Django Ninja

  1. Access authentication and context via the request instance

    master
    Unlike FastAPI, which uses dependency injection arguments (e.g., Depends(get_db)) in every function signature, Django Ninja uses the request instance attributes. This follows the standard Django view pattern, reducing verbosity in operations that rely on authentication or database sessions.
  2. Quickstart with Django Ninja

    master

    To create a basic API, follow these steps:

    1. Create an api.py file in your Django project (next to urls.py) and define your API instance and endpoints using NinjaAPI and type hints.
    2. Register the API routes in your project's urls.py by adding api.urls to your urlpatterns.
    # api.py
    from ninja import NinjaAPI
    
    api = NinjaAPI()
    
    @api.get("/add")
    def add(request, a: int, b: int):
        return {"result": a + b}
    # urls.py
    from .api import api
    
    urlpatterns = [
        path("admin/", admin.site.urls),
        path("api/", api.urls),  # <---------- !
    ]
  3. Mix sync and async operations in Django Ninja

    master

    Django Ninja automatically routes requests to the correct handler based on whether the function is defined with async or not. You can define both synchronous and asynchronous endpoints within the same API instance.

    @api.get("/say-sync")
    def say_after_sync(request, delay: int, word: str):
        time.sleep(delay)
        return {"saying": word}
    
    @api.get("/say-async")
    async def say_after_async(request, delay: int, word: str):
        await asyncio.sleep(delay)
        return {"saying": word}
  4. Expose CSRF token via ensure_csrf_cookie

    master

    If you need to provide a CSRF token to your frontend from an unprotected route, you can use Django's ensure_csrf_cookie decorator.

    Requirements and Constraints:

    • The route decorator must be placed above the ensure_csrf_cookie decorator.
    • You must apply @csrf_exempt to the route.
    • ensure_csrf_cookie only works on Django HttpResponse (or subclasses like JsonResponse), not on dictionaries.
    • If you have global Cookie-based authentication enabled on your API, you must explicitly disable it for this specific route using auth=None to avoid security exceptions.
    from django.http import HttpResponse
    from django.views.decorators.csrf import csrf_exempt, ensure_csrf_cookie
    
    @api.post("/csrf", auth=None)
    @ensure_csrf_cookie
    @csrf_exempt
    def get_csrf_token(request):
        return HttpResponse()
  5. Create a custom response renderer

    master

    To implement a custom media type for your API responses, inherit from ninja.renderers.BaseRenderer and override the render method. You must also define a media_type attribute on your class to set the Content-Type header. Finally, pass an instance of your renderer to the NinjaAPI constructor using the renderer argument.

    The render method signature is: render(self, request, data, *, response_status)

    Arguments:

    • request: The HttpRequest object.
    • data: The object that needs to be serialized.
    • response_status: An int representing the HTTP status code to be returned.
    from ninja import NinjaAPI
    from ninja.renderers import BaseRenderer
    
    
    class MyRenderer(BaseRenderer):
        media_type = "text/plain"
    
        def render(self, request, data, *, response_status):
            return ... # your serialization here
    
    api = NinjaAPI(renderer=MyRenderer())
  6. Use a custom favicon for API docs

    master

    To replace the default Ninja star favicon, override the ninja/favicons.html template in your project's template directories.

    <!-- templates/ninja/favicons.html -->
    {% load static %}
    
    {% block favicons %}
        <link rel="icon" type="image/png" href="{% static 'path/to/your/favicon.png' %}">
    {% endblock %}
  7. Parse input from the query string

    master

    To accept arguments from a URL's query string, add the desired argument names to your function signature. If an argument is provided without a default value, Django Ninja will return an HTTP 422 error if the parameter is missing from the request.

    You can specify a default value to make the parameter optional.

    @api.get("/hello")
    def hello(request, name):
        return f"Hello {name}"
    
    # With a default value to avoid 422 errors if 'name' is missing
    @api.get("/hello")
    def hello(request, name="world"):
        return f"Hello {name}"
  8. Parse input from the request body using Schemas

    master

    To accept arguments from the HTTP request body, you must define a Schema (an extension of a Pydantic Model) and use it as a type hint for a parameter in your function signature.

    from ninja import NinjaAPI, Schema
    
    api = NinjaAPI()
    
    class HelloSchema(Schema):
        name: str = "world"
    
    @api.post("/hello")
    def hello(request, data: HelloSchema):
        return f"Hello {data.name}"