Pythonic方法根据另一个类设置多个属性

时间:2014-11-19 02:30:39

标签: python django class model getter

当我只想将get传递给另一个对象时,是否有一种优雅的方法来处理类的所有get个请求?

这是一个Django项目,我有一个视频模型;视频可以来自不同的网站(例如,YouTube,Vimeo等)。该模型是通用的,将抓取相应的backend来解析数据(根据网站的不同,repr会有所不同。所有视频都具有相同的属性,但我有一个不同的backend来正确解析它们。这是一个例子:

BACKEND_VIDEO_TYPE = (
    (1, 'YouTube'),
    (2, 'Vimeo'),
)

class Video(ItemBase):
    video_id = models.CharField(max_length=25)
    video_type = models.PositiveIntegerField(choices=BACKEND_VIDEO_TYPE)
    video_data = models.TextField(editable=False)

    class Meta:
        unique_together = ("video_id", "video_type")

    def __init__(self, *args, **kwargs):
        super(Video, self).__init__(*args, **kwargs)

        for k, v in BACKEND_VIDEO_TYPE:
            if k == self.video_type:
                VideoBackend = import_string( 'video.backends.' + v )
                # load the backend that matches the video type and supply it with the data to parse
                self.backend = VideoBackend(self.video_id, self.video_data)

    @property
    def link(self):
        return self.backend.link

    @property
    def thumbnail(self):
        return self.backend.thumbnail

    @property
    def is_public(self):
        return self.backend.is_public()

    @property
    def duration(self):
        return self.backend.duration

我觉得这不是解决这个问题的最好方法,但我太新了,不知道该找什么。在确定要实现哪个后端类之后,是否有一种简单的方法return self.backend.property而无需添加后端中的每个属性?这个清单会变得相当长。通用__get__或类似的?

感谢您的帮助。

1 个答案:

答案 0 :(得分:1)

您可以覆盖__getattr__类上的Video,以便获取backend的属性。

def __getattr__(self, attr):
    try:
        return getattr(self.backend, attr)
    except:
        raise AttributeError('No attribute named ' + attr)

__getattr__只有在Video对象上找不到该属性时才会调用(例如,如果用户要求Video.video_id,则根本不会调用)所以&# 39;一种扩展Video类的暴露属性的简洁方法。缺点是可能不明显哪些属性可用,或者它可能会暴露您不希望的某些属性。您可以通过让VideoBackend类提供允许属性列表来解决这个问题。

def __getattr__(self, attr):
    if attr in self.backend.get_allowed_attr():
        return getattr(self.backend, attr)
    else:
        raise AttributeError('No attribute named ' + attr)