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

时间秒杀一切 提交于 2021-01-27 04:40:32

问题


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 },
),

回答1:


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).




回答2:


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.




回答3:


The way you've implemented your decorator, it is parameterised and therefore callable: that's why you've got the extra level of function that fizixx wrongly says is not required. You need to call the outer wrapper initially, in order to return the actual decorated function. So something like:

url(r'login/', 
 not_logged_in(auth_views.login)('/redirect/', 'redirect_field'), 
 {'authentication_form': LoginForm },
),


来源:https://stackoverflow.com/questions/5796897/wrapping-decorating-a-function-in-urls-py-vs-in-views-py

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!