django-ninja
django-ninja copied to clipboard
Apply decorators to a subset of routes/all paths under a sub-router
Recently, we found the need in Django to take an iterable of Django url configs and decorate the functions within them with something (in our case, observability functions to tag logs correctly).
With NinjaAPI, you can do this perfectly well with the .urls property on the top-level API. 🚀
However, if you want to decorate certain subroutes of that main API, it doesn't seem possible to do this.
For example:
router_1 = Router()
router_2 = Router()
# Imagine the routers gets a load of paths/functions registered to it...
api.add_router("prefix_1/", router_1)
api.add_router("prefix_2/", router_2)
urlpatterns = [
path("api/", api.urls)
]
Given that example, say I wanted to decorate all the functions under router_1
with decorator_1
and router_2
with decorator_2
. As far as I can tell, I am unable to do that. Instead, I have to decorate all the functions within those routers individually, which is obviously not ideal.
Could this be possible?
Hi @JimNero009
I guess the simpliest would be to extend Router and override it:
from ninja import Router
class RouterWithDecorator(Router):
def __init__(self, decorator, **kwargs):
self.decorator = decorator
super().__init__(**kwargs)
def add_api_operation(self, path, methods, view_func, **kwargs):
view_func = self.decorator(view_func)
return super().add_api_operation(path, methods, view_func, **kwargs)
def my_decorator(func):
@wraps
def wrapper(request, ...
...
router1 = RouterWithDecorator(my_decorator)
@router1.get('/foo')
def foo(request)
...
Hey @vitalik, nice idea. Will play with that. If that works fine, do you think it could be a candiate for first-class functionality? Perhaps a new kwargs accepting a list of decorators to apply, for example. I guess you'd have to assume the decorators passed in behaved nicely, but feels to me more of a user concern than NinjaAPI's.