基于Mixin的mongoengine文档与类装饰器而不是使用多重继承

时间:2014-10-15 22:17:45

标签: python mongoengine python-decorators

让我们假设我使用Mongoengine来创建像这样的文档:

class Tag(Document):
    name = fields.StringField(required=True, unique=True)
    user = fields.ReferenceField('User')
    created = fields.DateTimeField()
    updated = fields.DateTimeField(default=datetime.datetime.now)

createdupdated是在其他模型中经常使用的字段,我希望将与日期时间相关的内容的代码分隔为" mixin"。使用多重继承是一种解决方案:

class Tag(Timestampable, Document):
    name = fields.StringField(required=True, unique=True)
    user = fields.ReferenceField('User')

class Timestampable()
    created = fields.DateTimeField()
    updated = fields.DateTimeField(default=datetime.datetime.now)

虽然这有效,multiple inheritance in Python has its serious downsides。因此,我们需要另一种解决我想到了类装饰器:

@Timestampable
class Tag(Document):
    name = fields.StringField(required=True, unique=True)
    user = fields.ReferenceField('User')

def Timestampable(cls)
    cls.created = fields.DateTimeField()
    cls.updated = fields.DateTimeField(default=datetime.datetime.now)
    return cls

很酷,因为我不需要打扰任何super来电。

虽然不起作用。引用DateTimeField类时,不会创建Tag

我的问题有解决办法吗?

附录

为了正确理解对此的需求,这里是Timestampable装饰器的完整mixin代码:

def Timestampable(cls):
    cls.created = model_fields.DateTimeField()
    cls.updated = model_fields.DateTimeField(default=datetime.datetime.now)

    cls_save = cls.save
    def save(self, *args, **kwargs):
        now = datetime.datetime.now()
        if not self.id:
            self.created = now
        self.updated = now
        return cls_save(self, *args, **kwargs)
    cls.save = save

    return cls

0 个答案:

没有答案