【问题标题】:Decorating classes and classmethods装饰类和类方法
【发布时间】:2014-12-07 16:10:34
【问题描述】:

我想在装饰器中包装类的方法之一。如果有必要,我的类是基于 django 类的视图。

第一种实现是 method_decorator 的 wrap 方法

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"

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

我想要下一个:

@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 不包含原始的 classmethodsclassonlymethods。我猜想这种行为的原因。

如何将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'

【问题讨论】:

  • 那么您的意思是如果dispatchclassmethod,那么您的viewdecorator 将不起作用? classmethod 必须是最顶级的装饰器,但也许有一个解决方法。
  • viewdecorator 对我来说看起来不错,我不明白你的意思是“这个装饰器中的结果 cls 不包含原始的 classmethods 和 classonlymethods”?它肯定包含所有方法。您还需要将'dispatch' 设置为method_decorator(decorator)(dispatch).
  • @simonzack 不,你可以把@classmethod放在任何地方。
  • @AshwiniChaudhary 我不确定,请参阅stackoverflow.com/questions/1987919/…
  • 好的,在viewdecorator cls中不包含as_view、dispatch的方法。为什么?

标签: python django metaprogramming decorator


【解决方案1】:

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

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


class SimpleView(LoginRequiredMixin, View):
    pass

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

【讨论】:

  • 因此,我将获得一长串父母供查看。不是很好。在问题的最后,我写了有用的解决方案。
猜你喜欢
  • 2014-01-14
  • 2012-11-14
  • 2012-09-11
  • 1970-01-01
  • 1970-01-01
  • 2020-01-11
  • 1970-01-01
  • 2019-11-06
  • 2013-05-23
相关资源
最近更新 更多