Skip to content

# Welcome to Django Ninja 1.0

To get started install latest version with

    pip install -U django-ninja

django-ninja v1 is compatible with Python 3.7 and above.

Django ninja series 0.x is still supported but will receive only security updates and critical bug fixes

# What's new in Django Ninja 1.0

## Support for Pydantic2

Pydantic version 2 is re-written in Rust and includes a lot of improvements and features like:

- Safer types.
- Better extensibility.
- Better performance

By our tests average project can gain some 10% performance increase on average, while some edge parsing/serializing cases can give you 4x boost.

On the other hand it introduces breaking changes and pydantic 1 and 2 are not very compatible - but we tried or best to make this transition easy as possible. So if you used 'Schema' class migration to ninja v1 should be easy. Otherwise follow pydantic migration guide

Some features that are made possible with pydantic2

### pydantic context

Pydantic now supports context during validation and serialization and Django ninja passes "request" object during request and response work

    class Payload(Schema):
        id: int
        name: str
        request_path: str

        @staticmethod
        def resolve_request_path(data, context):
            request = context["request"]
            return request.get_full_path()

During response a "response_code" is also passed to context

## Schema.Meta

Pydantic now deprecates BaseModel.Config class. But to keep things consistent with all other django parts we introduce "Meta" class for ModelSchema - which works in a similar way as django's ModelForms:

    class TxItem(ModelSchema):
        class Meta:
            model = Transaction
            fields = ["id", "account", "amount", "timestamp"]

(The "Config" class is still supported, but deprecated)

## Shorter / cleaner parameters syntax

    @api.post('/some')
    def some_form(request, username: Form[str], password: Form[str]):
        return True

instead of

    @api.post('/some')
    def some_form(request, username: str = Form(...), password: str = Form(...)):
        return True

or

    @api.post('/some')
    def some_form(request, data: Form[AuthSchema]):
        return True

instead of

    @api.post('/some')
    def some_form(request, data: AuthSchema = Form(...)):
        return True

with all the autocompletion in editors

On the other hand the old syntax is still supported so you can easily port your project to a newer django-ninja version without much haste

#### + Annotated

typing.Annotated is also supported:

    @api.get("/annotated")
    def annotated(request, data: Annotated[SomeData, Form()]):
        return {"data": data.dict()}

## Async auth support

The async authenticators are finally supported. All you have to do is just add `async` to your `authenticate` method:

    class Auth(HttpBearer):
        async def authenticate(self, request, token):
            await asyncio.sleep(1)
            if token == "secret":
                return token

## Changed CSRF Behavior

`csrf=True` requirement is no longer required if you use cookie based authentication. Instead CSRF protection is enabled automatically. This also allow you to mix csrf-protected authenticators and other methods that does not require cookies:

    api = NinjaAPI(auth=[django_auth, Auth()])

## Docs

Doc viewer are now configurable and plugable. By default django ninja comes with Swagger and Redoc:

    from ninja import NinjaAPI, Redoc, Swagger

    # use redoc
    api = NinjaAPI(docs=Redoc()))

    # use swagger:
    api = NinjaAPI(docs=Swagger())

    # set configuration for swagger:
    api = NinjaAPI(docs=Swagger({"persistAuthorization": True}))

Users now able to create custom docs viewer by inheriting `DocsBase` class

## Router

add_router supports string paths:

    api = NinjaAPI()

    api.add_router('/app1', 'myproject.app1.router')
    api.add_router('/app2', 'myproject.app2.router')
    api.add_router('/app3', 'myproject.app3.router')
    api.add_router('/app4', 'myproject.app4.router')
    api.add_router('/app5', 'myproject.app5.router')

## Decorators

When django ninja decorates a view with .get/.post etc. - it wraps the result of the function (which in most cases are not HttpResponse - but some serializable object) so it's not really possible to use some built-in or 3rd-party decorators like:

    from django.views.decorators.cache import cache_page

    @api.get("/test")
    @cache_page(5) # <----- will not work
    def test_view(request):
        return {"some": "Complex data"}

This example does not work.

Now django ninja introduces a decorator decorate_view that allows inject decorators that work with http response:

    from ninja.decorators import decorate_view

    @api.get("/test")
    @decorate_view(cache_page(5))
    def test_view(request):
        return str(datetime.now())

## Paginations

`paginate_queryset` method now takes `request` object

#### Backwards incompatible stuff

- resolve_xxx(self, ...) - support resolve with (self) is dropped in favor of pydantic build-in functionality
- pydantic v1 is no longer supported
- python 3.6 is no longer supported

BTW - if you like this project and still did not give it a github start - please do so