Django Ninja – Fast Django REST Framework for Building APIs
github.com
github.com
https://django-ninja.rest-framework.com/motivation/
It sounds super interesting, it fits the middle ground between Django Rest Framework and FastAPI taking the best of both. Full support for Django and particularly it’s ORM (hard to do with FastAPI as the Django ORM is not yet async and can’t be used with FastAPI)
I like that it supports both sync and async as I’m personally not convinced about the use of async Python everywhere. I could see this being brilliant for an api where the majority is simple sync code but with a few endpoint with long running responses or where you need multiple concurrent requests to DBS or other APIs.
(Edited for clarity, thanks vladvasiliu)
I think you may have it backwards. Django's ORM isn't async yet [1], whereas FastAPI doesn't actually have an "included" ORM. However, the docs give an example of an async ORM [2], and SQLAlchemy also has async support [3].
---
[1] https://docs.djangoproject.com/en/4.0/topics/async/: We’re still working on async support for the ORM
[2] https://fastapi.tiangolo.com/advanced/async-sql-databases/
[3] https://docs.sqlalchemy.org/en/14/orm/extensions/asyncio.htm...
Full support for Django and particularly it’s ORM (hard to do with FastAPI as the Django ORM is not yet async and can’t be used with FastAPI)
Will edit to make clear.
Plans exist to make the Django Queryset async, so it’ll be exciting when that day comes!
https://github.com/django/django/pull/14843
So far they are only going down the the queryset level, it then uses a thread pool for the db connector, next job would be to support async db connections.
https://github.com/tiangolo/sqlmodel
I have not yet used it, but I think that’s the best approach now
SQLModel 100 issues, 54 open PRs
FastAPI 903 issues, 448(!!) open PRs
I recently had to choose between Flask and FastAPI for a fresh project and went with Flask in the end, partly due to long term maintenance concerns with FastAPI.
1. https://github.com/collerek/ormar 2. https://github.com/tophat/ormar-postgres-extensions/
> Benchmark: 750 requests per second.
Think we're gonna need a couple of zeroes on that number to throw around words like "very high performance".
this is pure CPU-heavy single core synthetic test - this is just to give an idea how it compares the speed to flask/drf on the same environment
1. A custom made serializer. This is the most complicated 150 lines of code in that it can traverse Django ORM objects/query sets and output them to JSON. It supports explicit included and excluded fields and included relationships which it automatically prefetches.
2. Custom middleware that parses any application/json request bodies in request.data.
3. I use Django forms on any data going from client to server for validation. Works great, no reason to make this complicated.
That’s it. Now I can have a REST API written as normal Django views. It is significantly more performant Thant DRF since it doesn’t need to check for a whole lot of different complicated field types when serializing. It’s easy to understand (just call serialize(users, excluded_fields=[“password”], relationships=[“books.chapters”]) to return JSON to the client; you can also annotate your models to include/exclude fields and relationships by default). It has validation errors built in via Django forms. It just works.
Never saw the need for API testing if I am the user of the API.
It does indeed have a standardized format.
Non-cookie auth is actually handled in some of my projects with about a dozen lines of a header parser that then passes it to Django sessions.
Pagination in my latest project is handled as date filters or done client side. Way faster for the user that way and removes a lot of PITA.
Throttling is handled by other bits of infrastructure. If you do that inside a Django view or middleware you are likely doing it wrong.
Frankly it’s not hard to do: you need a parser for author.books.chapters, then a bit of code to look up fields from a model’s Meta class, and then a recursive function to traverse model instances and include the correct field/value pairs based on the type that each field is (scalar, iterable, dict, model instance). My latest version includes a couple of niceties like the annotation on the models of fields to always include/exclude, support for custom properties, and caching of the above. The output is a dict or a list of dicts that can be serialized by Django’s JSON serializer.
Django actually sort of includes a version of this already for serializing model instances, it’s just not very robust.
This is the bit I find not really true.
My needs are simple (10-20 basic get/post/put/delete APIs, many at the business logic layer than true REST) but I still would really like the OpenAPI docs, auto-generated schema definitions, etc etc. If I can get that with just some simple decorators on my existing views and pydantic models for the inputs and outputs .... that would be awesome.
I'm excited to try this out, been looking at FastAPI.
Having written years worth of django/drf in the past, it's a breathe of fresh air with minimal dependencies, simple constructs, and good documentation. Def recommend.
I've been using django ninja for months and I can say that it's a very good replacement to DRF. It's way simpler to use and less bloated, thanks to pydantic.
However I would not use it for important projects in production, because of a lack of support and documentation, and the fact that it relies almost entirely on a single developer (like many other projects, right).