Reputation: 1764
I know the suggested way to do this is middleware, but I'd like to implement the following to add in an api_env
variable, accessed at run-time, so that my view can access it:
@api_wrapper
def my_view(request):
print api_env # this is the variable I want, such as request.epi_env
And the decorator:
def api_wrapper(func):
def api_inner(request):
request.api_env = 'something'
return func(request)
return api_inner
What's the best way to do this? I have about 100 functions to wrap so I don't want to add in a new parameter for every function but would just like to use the simplest approach to pass that 'env' variable. How should I do it.
Upvotes: 0
Views: 597
Reputation: 363
Try this:
def api_wrapper():
def decorator(view_func):
@wraps(view_func)
def _wrapped_view(req, *args, **kwargs):
req.env = 'something'
return view_func(req, *args, **kwargs)
return _wrapped_view
return decorator
Upvotes: 1
Reputation: 476534
You can generalize this to work with an arbitrary number of positional and named parameters. Furthermore you might want to use update_wrapper
[Python-doc], to add attributes like csrf_exempt
to the "output" view, otherwise the @csrf_except
will not be available in the outer function:
from functools import update_wrapper
def api_wrapper(func):
def api_inner(request, *args, **kwargs):
request.api_env = 'something'
return func(request, *args, **kwargs)
update_wrapper(api_inner, func, assigned=())
return api_inner
That being said, this to some extent shows that using class-based views might be better in this case, since then one can define a mixin, and just mix it in the method resolution order (MRO) as a reusable component. In that case, one often do not have to take into account more complicated logic like the parameters, or the attributes that are added to the function, since a class-based view takes care of this itself.
Upvotes: 1