Skip to content
Advertisement

Use a decorator to add in a variable to request

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.

Advertisement

Answer

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.

Advertisement