43 lines
1.3 KiB
Python
43 lines
1.3 KiB
Python
from functools import partial
|
|
from typing import Any, Callable, Tuple
|
|
|
|
from ninja.operation import Operation
|
|
from ninja.types import TCallable
|
|
from ninja.utils import contribute_operation_callback
|
|
|
|
# Since @api.method decorator is applied to function
|
|
# that is not always returns a HttpResponse object
|
|
# there is no way to apply some standard decorators form
|
|
# django stdlib or public plugins
|
|
#
|
|
# @decorate_view allows to apply any view decorator to Ninja api operation
|
|
#
|
|
# @api.get("/some")
|
|
# @decorate_view(cache_page(60 * 15)) # <-------
|
|
# def some(request):
|
|
# ...
|
|
#
|
|
|
|
|
|
def decorate_view(*decorators: Callable[..., Any]) -> Callable[[TCallable], TCallable]:
|
|
def outer_wrapper(op_func: TCallable) -> TCallable:
|
|
if hasattr(op_func, "_ninja_operation"):
|
|
# Means user used decorate_view on top of @api.method
|
|
_apply_decorators(decorators, op_func._ninja_operation) # type: ignore
|
|
else:
|
|
# Means user used decorate_view after(bottom) of @api.method
|
|
contribute_operation_callback(
|
|
op_func, partial(_apply_decorators, decorators)
|
|
)
|
|
|
|
return op_func
|
|
|
|
return outer_wrapper
|
|
|
|
|
|
def _apply_decorators(
|
|
decorators: Tuple[Callable[..., Any]], operation: Operation
|
|
) -> None:
|
|
for deco in decorators:
|
|
operation.run = deco(operation.run) # type: ignore
|