Search code examples
pythondjangopython-decorators

Django - custom decorator - parameter unfilled


I'm trying to create an own decorator which checks if the user meet some condition (for example user.is_authenticated) and if this condition doesn't hold, they are going to be redirected to another page (second parameter).

The problem is that the decorator doesn't work because it wants another parameter (the view function).

from django.http import HttpResponseRedirect
from django.core.urlresolvers import reverse


def condition_or_redirect(view_func, condition, redirect_to):
    def wrapped(request, *args, **kwargs):
        if not condition(request.user):
            return HttpResponseRedirect(reverse(redirect_to))
        else:
            return view_func(request, *args, **kwargs)
    return wrapped

Then I want to use it:

@condition_or_redirect(lambda x: not x.is_authenticated,'homepage')
def some_view....

What is wrong with the code? I know that it want's the first parameter which is a view_func but I thought that it is added by decorator itself.


Solution

  • When you want to pass parameters to a decorator, you need to define a third level of nesting; the first level accepts the parameters and returns the second level, which takes the function itself. So:

    def condition_or_redirect(condition, redirect_to):
        def wrapper(view_func):
            def wrapped(request, *args, **kwargs):
                if not condition(request.user):
                    return HttpResponseRedirect(reverse(redirect_to))
                else:
                    return view_func(request, *args, **kwargs)
            return wrapped
        return wrapper