Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Wrapping/decorating a function in urls.py vs in views.py

So, I'm pretty familiar with wrapping functions in views.py. So I've written a decorator to redirect to the default REDIRECT_URL if the user is logged in (sort of a reverse login_required); it's based on how I've made views in the past:

def not_logged_in(redirect_url=None, redirect_field_name=REDIRECT_FIELD_NAME):
    def decorator(view_func, *args, **kwargs):
        def wrapper(request, *args, **kwargs):
            if not request.user.is_authenticated():
                return view_func(*args, **kwargs)
            else:
                redirect_url = (request.REQUEST.get(redirect_field_name, redirect_url) or
                                settings.REDIRECT_URL)
                return HttpResponseRedirect(redirect_url)
        return wrapper
    return decorator

However, I get the following error: 'function' object has no attribute 'status_code' which is caused by a MiddleWare expecting an HttpResponse. When I look at the value for response, I see that it's <function wrapper at 0x2b3a9922a500>.

Here's how I'm calling it in urls.py:

url(r'login/', 
     not_logged_in(auth_views.login), 
     {'authentication_form': LoginForm },
),
like image 360
Jordan Reiter Avatar asked Apr 26 '11 21:04

Jordan Reiter


People also ask

Which function is the decorator?

A decorator in Python is a function that takes another function as its argument, and returns yet another function . Decorators can be extremely useful as they allow the extension of an existing function, without any modification to the original function source code.

How does decorators work in Python?

Decorators dynamically alter the functionality of a function, method, or class without having to directly use subclasses or change the source code of the function being decorated. Using decorators in Python also ensures that your code is DRY(Don't Repeat Yourself).

Can you decorate a variable in Python?

No, decorator syntax is only valid on functions and classes.


2 Answers

Here’s my implementation of the same thing.

def logout_required(view):
    def f(request, *args, **kwargs):
        if request.user.is_anonymous():
            return view(request, *args, **kwargs)
        return HttpResponseRedirect(settings.LOGIN_REDIRECT_URL)
    return f

In urls.py:

urlpatterns = patterns("",
    url(r"^login/", logout_required(login), {"template_name": "users/login.html"}, "login"),
    # ...

I hope this helps (unsure though).

like image 143
ayanami Avatar answered Sep 23 '22 00:09

ayanami


The first argument to a decorator should be the function that needs to be decorated.

def not_logged_in(func, redirect_url=None, redirect_field_name=REDIRECT_FIELD_NAME):

The decorator function is also not needed. Return the wrapper function from not_logged_in.

like image 20
fizixx Avatar answered Sep 20 '22 00:09

fizixx