Python装饰器将方法限制为特定类?

时间:2012-12-23 15:32:18

标签: python django django-models

我有一个由一些Django项目/网站共享的大型Django应用程序库。在每个项目/站点内,都可以选择定义“混合”和“混合”。将被混合到其中一个库内基类的类(许多模型的子类来自)。

对于此示例,我们假设库内基类为PermalinkBase,混合类为ProjectPermalinkBaseMixIn

因为来自PermalinkBase的许多模型是子类,所以ProjectPermalinkBaseMixIn中定义的所有方法/特性都不会被PermalinkBase的所有子类使用。

我想编写一个可以应用于ProjectPermalinkBaseMixIn中的方法/属性的装饰器,以便限制它们运行(或者至少返回None),如果它们是从未经批准的课程。

以下是我现在的表现:

class ProjectPermalinkBaseMixIn(object):
    """
    Project-specific Mix-In Class to `apps.base.models.PermalinkBase`
    """

    def is_video_in_season(self, season):
        # Ensure this only runs if it is being called from the video model
        if self.__class__.__name__ != 'Video':
            to_return = None
        else:
            videos_in_season = season.videos_in_this_season.all()
            if self in list(videos_in_season):
                to_return = True
            else:
                to_return False

        return to_return

以下是我喜欢的方式:

class ProjectPermalinkBaseMixIn(object):
    """
    Project-specific Mix-In Class to `apps.base.models.PermalinkBase`
    """

    @limit_to_model('Video')
    def is_video_in_season(self, season):
        videos_in_season = season.videos_in_this_season.all()
        if self in list(videos_in_season):
            to_return = True
        else:
            to_return = False

        return to_return

装饰器可以吗? This answer帮助我更好地理解装饰器,但我无法弄清楚如何修改它以解决我上面列出的问题。

装饰师是否适合这项工作?如果是这样,我将如何编写limit_to_model装饰器功能?如果没有,那么解决这个问题的最佳方法是什么?

1 个答案:

答案 0 :(得分:1)

正在查看您的问题,我认为这可能是一种过于复杂的方式来实现您的目标。但是我写了这段代码:

def disallow_class(*klass_names):
    def function_handler(fn):
        def decorated(self, *args, **kwargs):
            if self.__class__.__name__ in klass_names:
                print "access denied to class: %s" % self.__class__.__name__
                return None
            return fn(self, *args, **kwargs)
        return decorated
    return function_handler


class MainClass(object):

    @disallow_class('DisallowedClass', 'AnotherDisallowedClass')
    def my_method(self, *args, **kwargs):
        print "my_method running!! %s" % self


class DisallowedClass(MainClass): pass

class AnotherDisallowedClass(MainClass): pass

class AllowedClass(MainClass): pass


if __name__ == "__main__":
    x = DisallowedClass()
    y = AnotherDisallowedClass()
    z = AllowedClass()
    x.my_method()
    y.my_method()
    z.my_method()

如果在命令行上运行这段代码,输出将类似于:

access denied to class: DisallowedClass
access denied to class: AnotherDisallowedClass
my_method running!! <__main__.AllowedClass object at 0x7f2b7105ad50>

此致