Django:员工装饰器

62

我正在尝试为Django编写一个“仅限工作人员”的装饰器,但似乎无法使其正常工作:

def staff_only(error='Only staff may view this page.'):
    def _dec(view_func):
        def _view(request, *args, **kwargs):
            u = request.user
            if u.is_authenticated() and u.is_staff:
                return view_func(request, *args, **kwargs)
            messages.error(request, error)
            return HttpResponseRedirect(request.META.get('HTTP_REFERER', reverse('home')))
        _view.__name__ = view_func.__name__
        _view.__dict__ = view_func.__dict__
        _view.__doc__ = view_func.__doc__
        return _view
    return _dec

尝试跟从这里的示例: http://passingcuriosity.com/2009/writing-view-decorators-for-django/,但是遇到以下错误:

'WSGIRequest' object has no attribute '__name__'

如果我将这3行代码删除,只会得到一个无用的"Internal Server Error"。我在这里做错了什么?

4个回答

阿里云服务器只需要99元/年,新老用户同享,点击查看详情
171

1
另外,问题在于它没有显示错误消息指示问题所在。我的客户很可能会尝试访问员工页面,而没有员工用户帐户。 - mpen
Luke(或Mark),使用源代码!在django/contrib/admin/views/decorators.py(1.1.1版本中的第26行)中,你会找到这个函数,在第71行你会看到if user.is_active and user.is_staff:,它决定了赞/踩的结果。这个特定的装饰器比普通的要复杂一些的唯一原因是它可能会触发一个登录序列作为副作用。如果你需要它做更多的事情(例如不同的错误消息),你可以复制一份然后在适当的地方调用你自己的装饰器。 - Peter Rowell
@Peter:卢克是谁?在这种情况下,源代码并不是很有帮助,因为它不接受修饰符的参数,我认为这就是导致我的问题的原因。 - mpen
7
@马克:卢克是卢克·天行者!奥比万·克诺比(http://en.wikipedia.org/wiki/Obi-Wan_Kenobi)是在《星球大战四部曲》中(实际上是第一部出品的电影),说过“卢克!使用原力!”。修饰符通常只需要一个参数,即要修饰的函数。如果您需要添加更多参数,请查看教程。(例如,http://www.artima.com/weblogs/viewpost.jsp?thread=240845)如果当前的修饰符不能满足您的需求,请“复制”它并进行更改!这就是开源的本质。 - Peter Rowell
我以为是“使用原力”?这个词游戏很可爱啊 ;) 不过,这不就是我所做的吗?我的代码看起来很像你指出的例子... 哦,好吧... 看来我得自己想办法了。 - mpen

27

对于基于类的视图(Class Based View),您可以像这样装饰视图类的调度(dispatch)方法:

from django.contrib.admin.views.decorators import staff_member_required
from django.utils.decorators import method_decorator


@method_decorator(staff_member_required, name='dispatch')
class ExampleTemplateView(TemplateView):
    ...

11

这种装饰器函数的风格是用于带参数的装饰器——例如当你执行:

@staffonly(my_arguments)
def function(request):
    blah

如果你实际上没有调用外部函数,也就是像这样使用它:

@staffonly
def function(request):

你将得到奇怪的结果,因为函数对象将会被传递给装饰器中错误的嵌套函数之一。


哦...那我该怎么办呢? - mpen
1
我开始理解了,所以如果我的视图中有多个函数,我必须在每个函数前面添加@staffonly吗? - David 天宇 Wong

0

我使用了Your Decorator,但只遇到了一个错误:

'bool' object is not callable

这个错误来自于这里 if u.is_authenticated() and u.is_staff: 我将 u.is_authenticated() 改为 u.is_authenticated,然后它就可以正常工作了。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,