装饰课程和课堂方法

时间:2014-10-13 06:32:12

标签: python django metaprogramming decorator

我想在decorator中包装一个类的方法。如果有必要,我的课程是基于django类的视图。

第一种类型的实现是 method_decorator 的包装方法:

class MyView(View):
   template_name = "index.html"
   @method_decorator(login_required):
   def dispatch(self, *args, **kwargs):
       return super(MyView, self).dispatch(*args, **kwargs)

好的,这很有效。但我不想每次都覆盖方法 dispatch

第二种方式 - mixins和多重继承。

class LoginRequiredView(object):
   @method_decorator(login_required):
   def dispatch(self, *args, **kwargs):
       return super(MyView, self).dispatch(*args, **kwargs)

class MyView(LoginRequiredView, View):
   template_name = "index.html"

这也有效。但是如果我想使用多个装饰器,则需要在父级中列出所有mixins。这对我来说不是很好。

我想要下一个:

@viewdecorator(login_required)
class MyView(LoginRequiredView, View):
   template_name = "index.html"

我的问题是如何实现 viewdecorator 。我试着写这个:

def viewdecorator(decorator):
    def wrap(cls):
        dispatch = getattr(cls, 'dispatch', None)
        if dispatch:
            setattr(cls, 'dispatch', method_decorator(decorator))
        return cls
    return wrap

但是这个装饰器中产生的cls不包含原始的 classmethods classonlymethods 。我猜这种行为的原因。

如何将 viewdecorator 写入 classmethods 将在结果cls中显示?

UPD:我理解了这项工作以及实际工作代码如下所示

def viewdecorator(decorator):
    def wrap(cls):
        getattribute = cls.__getattribute__

        def newgetattr(cls, name):
            attr = getattribute(cls, name)
            if name == 'dispatch':
                return decorator(method_decorator(attr))
            return attr 

        cls.__getattribute__ = newgetattr
        return cls
    return wrap

@viewdecorator(login_required)
@viewdecorator(csrf_exempt)
class EntriesMyList(EntriesList):
    template_name = 'index.html'

1 个答案:

答案 0 :(得分:0)

您可以安装django-braces。该库包含登录所需的mixin

from django.views.generic import View
from braces.views import LoginRequiredMixin


class SimpleView(LoginRequiredMixin, View):
    pass

对于正确的款式,您不需要CBV装饰器。如果您需要一些自定义视图权限,请在dispatch视图方法中实现逻辑。