我正在使用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')
我的模板中有一个链接到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')
时,该网址没有问题并成功加载它。到底是怎么回事?
这是装饰者的代码:
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
?
答案 0 :(得分:2)
您需要将包装函数的名称(由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__
属性会命名您定义装饰器的模块,这意味着要反转视图必须使用decorator_module.wrapper
作为查找。但是,使用装饰器的任何视图都将以该名称注册。
答案 1 :(得分:1)
您可以在不更改装饰器的情况下解决此问题,方法是为您的网址指定一个特定的name
属性,并反过来使用它:
url(r'^create_user$', views.create_user, name='create_user'),