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 seres 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 the autocompletion in editors
On the other hand the old syntax is still supported so you can easy 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 requrie 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"}
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