Django:员工装饰师

Posted

技术标签:

【中文标题】Django:员工装饰师【英文标题】:Django: Staff Decorator 【发布时间】:2011-02-11 05:42:57 【问题描述】:

我正在尝试为 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

尝试follow lead from here。我得到:

'WSGIRequest' object has no attribute '__name__'

但如果我去掉这 3 行,我只会得到一个无用的“内部服务器错误”。我在这里做错了什么?

【问题讨论】:

【参考方案1】:

这种风格的装饰器函数与参数化装饰器一起使用 - 例如,当你这样做时:

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

如果您实际上并没有调用外部函数,即您正在像这样使用它:

@staffonly
def function(request):

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

【讨论】:

哦...那我该如何解决呢? 我开始明白了,所以如果我的视图中有多个函数,我必须在每个函数前面添加@staffonly?【参考方案2】:

这个装饰器已经存在

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

@staff_member_required

后备箱: http://code.djangoproject.com/browser/django/trunk/django/contrib/admin/views/decorators.py

【讨论】:

另外,问题在于它没有显示指示问题所在的错误消息。我的客户很可能会在没有员工用户帐户的情况下尝试访问员工页面。 卢克(或马克),使用源代码!在django/contrib/admin/views/decorators.py(1.1.1 版本中的第 26 行)中,您会找到这个函数,在第 71 行,您会看到if user.is_active and user.is_staff:,它给出了赞成/反对的决定。这个特殊的装饰器比正常情况复杂一点的唯一原因是它可以触发登录序列作为副作用。如果您需要它做更多事情(例如不同的错误消息),您可以随时制作副本,然后在适当的地方调用您自己的装饰器。 @Peter:卢克是谁?在这种情况下,源不是很有帮助,因为它不接受装饰器的参数,我认为这是导致我的问题的原因。 @Mark:卢克是……卢克·天行者! Obi Wan Kenobi (en.wikipedia.org/wiki/Obi-Wan_Kenobi) 说:“卢克!使用源头!”在《星球大战 IV》中(这实际上是第一部电影)。装饰器通常只接受一个参数,即要装饰的函数。如果您需要添加更多参数,请查看教程。 (例如artima.com/weblogs/viewpost.jsp?thread=240845)如果当前的装饰器不能满足你的需要,复制它并改变它!这就是开源的精髓。 我以为是“使用原力”?可爱的文字游戏;)这不是我所做的吗?我的代码看起来很像您指出的示例......哦,好吧......我想我必须自己弄清楚。【参考方案3】:

对于基于类的视图,您可以像这样装饰视图类的调度方法:

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

【讨论】:

以上是关于Django:员工装饰师的主要内容,如果未能解决你的问题,请参考以下文章

架构师之路--装饰模式

架构师之路--装饰模式

架构师之路--装饰模式

架构师内功心法,有重构项目经验必备的装饰者模式详解

架构师内功心法,有重构项目经验必备的装饰者模式详解

设计模式 -- 装饰模式