Skip to content

Welcome to Django Ninja 1.0

To get started, install the latest version using the following command:

pip install -U django-ninja

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

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

✨ What's new in Django Ninja 1.0

Pydantic2 support

Pydantic version 2 is rewritten in Rust and includes many improvements and features, such as:

  • Safer types.
  • Better extensibility.
  • Better performance.

According to our tests, an average project can gain about a 10% performance improvement on average, while in some edge parsing/serialization scenarios you can get a 4x boost. On the other hand, it introduces breaking changes — pydantic 1 and 2 are not fully compatible — but we have tried to make this transition as easy as possible. So if you used the 'Schema' class, migrating to ninja v1 should be straightforward. Otherwise, please follow the pydantic migration guide

Some new features provided by pydantic2

pydantic context

Pydantic now supports context during validation and serialization, and Django Ninja passes the "request" object through during request and response handling.

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 the response phase, "response_code" is also passed to the context.

Schema.Meta

Pydantic has now deprecated the BaseModel.Config class. However, to stay consistent with all other Django parts, we introduced a "Meta" class for ModelSchema — it works similarly to Django's ModelForms:

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

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

Shorter/cleaner parameter 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

as well as all the autocompletion features in your editor.

On the other hand, the old syntax is still supported, so you can effortlessly port your project to the latest django-ninja version.

+ Annotated

typing.Annotated is also now supported:

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

Async auth support

Async authenticators are finally supported. All you have to do is 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 is no longer required if you use cookie-based authentication. Instead, CSRF protection is enabled automatically. This also lets you mix CSRF-protected authenticators with other methods that don't require cookies:

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

Documentation

The documentation viewer is now configurable and pluggable. By default, django-ninja ships 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 can now create custom documentation viewers by subclassing the 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 (in most cases not an HttpResponse - but some serializable object), so it is unlikely to work with some built-in or third-party decorators, such as:

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 will not work.

Now django-ninja introduces a decorate_view decorator that allows injecting decorators that work with http responses:

from ninja.decorators import decorate_view

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

Pagination

The paginate_queryset method now accepts the request object

Backward-incompatible items

  • resolve_xxx(self, ...) - support for (self) resolution is deprecated in favor of pydantic's built-in functionality.
  • pydantic v1 is no longer supported
  • python 3.6 is no longer supported

By the way - if you like this project and haven't given it a GitHub star yet - please do so! github star

Comments


本文总阅读量次