应用装饰器查看 - url 没有被反向找到
Applying decorator to view - url not being found by reverse
我正在使用 django 1.7
和模块 django-role-permissions
。
在我的 login/urls.py
:
from django.conf.urls import patterns, url
from . import views
urlpatterns = patterns('',
url(r'^$', views.login),
url(r'^logout$', views.logout),
url(r'^create_user$', views.create_user),
)
并在 login/views.py
中:
@has_role_decorator('EbagManager')
def create_user(request):
return HttpResponse('OK')
我的模板中有一个 link 到 create_user
:<a href="{% url 'login.views.create_user' %}">Create User</a>
然后我得到了 Django 异常:
NoReverseMatch at /core/index
Reverse for 'login.views.create_user' with arguments '()' and keyword arguments '{}' not found. 0 pattern(s) tried: []
然而,当我删除 @has_role_decorator('EbagManager')
时 url 没有问题并成功加载它。到底是怎么回事?
这是装饰器的代码:
def has_role_decorator(role):
def request_decorator(dispatch):
def wrapper(request, *args, **kwargs):
user = request.user
if user.is_authenticated():
if has_role(user, role):
return dispatch(request, *args, **kwargs)
raise PermissionDenied
return wrapper
return request_decorator
对我来说似乎完全没问题。为什么这个装饰器会破坏 reverse
?
您需要将包装函数的名称(由 dispatch
引用)复制到您的 wrapper
函数中。使用 @functools.wraps()
decorator factory:
最简单
from functools import wraps
def has_role_decorator(role):
def request_decorator(dispatch):
@wraps(dispatch)
def wrapper(request, *args, **kwargs):
user = request.user
if user.is_authenticated():
if has_role(user, role):
return dispatch(request, *args, **kwargs)
raise PermissionDenied
return wrapper
return request_decorator
不使用 @functools.wraps()
,create_user.__name__
设置为 'wrapper'
,create_user.__module__
属性将命名您定义装饰器的模块,这意味着反转view 你必须使用 decorator_module.wrapper
作为查找。但是,任何使用装饰器的视图都将以该名称注册。
你可以在不改变装饰器的情况下解决这个问题,方法是给你的 URL 一个特定的 name
属性,然后反过来使用它:
url(r'^create_user$', views.create_user, name='create_user'),
我正在使用 django 1.7
和模块 django-role-permissions
。
在我的 login/urls.py
:
from django.conf.urls import patterns, url
from . import views
urlpatterns = patterns('',
url(r'^$', views.login),
url(r'^logout$', views.logout),
url(r'^create_user$', views.create_user),
)
并在 login/views.py
中:
@has_role_decorator('EbagManager')
def create_user(request):
return HttpResponse('OK')
我的模板中有一个 link 到 create_user
:<a href="{% url 'login.views.create_user' %}">Create User</a>
然后我得到了 Django 异常:
NoReverseMatch at /core/index
Reverse for 'login.views.create_user' with arguments '()' and keyword arguments '{}' not found. 0 pattern(s) tried: []
然而,当我删除 @has_role_decorator('EbagManager')
时 url 没有问题并成功加载它。到底是怎么回事?
这是装饰器的代码:
def has_role_decorator(role):
def request_decorator(dispatch):
def wrapper(request, *args, **kwargs):
user = request.user
if user.is_authenticated():
if has_role(user, role):
return dispatch(request, *args, **kwargs)
raise PermissionDenied
return wrapper
return request_decorator
对我来说似乎完全没问题。为什么这个装饰器会破坏 reverse
?
您需要将包装函数的名称(由 dispatch
引用)复制到您的 wrapper
函数中。使用 @functools.wraps()
decorator factory:
from functools import wraps
def has_role_decorator(role):
def request_decorator(dispatch):
@wraps(dispatch)
def wrapper(request, *args, **kwargs):
user = request.user
if user.is_authenticated():
if has_role(user, role):
return dispatch(request, *args, **kwargs)
raise PermissionDenied
return wrapper
return request_decorator
不使用 @functools.wraps()
,create_user.__name__
设置为 'wrapper'
,create_user.__module__
属性将命名您定义装饰器的模块,这意味着反转view 你必须使用 decorator_module.wrapper
作为查找。但是,任何使用装饰器的视图都将以该名称注册。
你可以在不改变装饰器的情况下解决这个问题,方法是给你的 URL 一个特定的 name
属性,然后反过来使用它:
url(r'^create_user$', views.create_user, name='create_user'),