I've been evaluating django-ninja recently, using it in a personal project to see when it might be appropriate for our clients.
The Problem - How to have multiple view files
One thing that was not clear was how to break up your API views and sprinkle them around in multiple files. The default tutorial and documentation is not bad, but just does not cover this small thing.
The way django-ninja works is that you decorate functional views with @api
where you indicate what HTTP method it is for and some other parameters.
Everything is perfect until you realize your views.py has grown huge or you
want to include api views from several Django applications.
For those of us who are very familiar with DRF, it is not immediately clear how you can break your views into multiple files.
Let's use an example of having a Django apps named core
, users
, and posts
to mimic some sort of blog like software and our project directory, which contains
our settings and urls files will be named config/
which is the standard way
we roll at REVSYS.
Your first guess might be that you should create another instance of NinjaAPI
and use that to decorate your views in each file. Unfortunately, because of how
the internal registry works for these, that would create multiple django-ninja
"sites", each with their own docs, etc. which is obviously not what we want.
The Solution
The easiest way to do this is to pass around your API decorator and ensure your view files are imported before you call on Ninja to generate your URLs.
While I hate having an app named core
, I used it in this case. So we
create our API instance with the following:
# File: core/api.py
from ninja import NinjaAPI
api = NinjaAPI(csrf=True)
And then in our views we import this and use it:
# File: users/views.py
from core.api import api
@api.get("users/something/"):
def get_user(request):
# ... do something interesting here ...
# File: posts/views.py
from core.api import api
@api.get("posts/{username}/"):
def get_posts(requests, username: str):
# ... do something interesting here ...
Then the final bit is to make sure we import these files in our urls.py
before
we call api.urls
like this:
# File: config/urls.py
import users.views
import posts.views
from core.api import api
urlpatterns = [
path("api/", api.urls),
]
Alternative Solution
Turns out there is also a DRF like concept of routers which is honestly probably a better more maintainable solution than the above.
Thanks to Ville Säävuori for point this out after I posted this.
Hopefully, this saves you a bit of time when you first start using django-ninja!
If you need help creating Django REST APIs don't hesitate to reach out to us!