有没有一种在Django模型中模拟虚拟继承的理智方法?

时间:2012-02-18 19:07:55

标签: python django oop inheritance virtual-inheritance

我想记录用户所做的操作。在大多数OO语言中,我将通过LoggedAction类实现此功能,具有多个子类,如LoginActionLogoutAction。然后,我可以迭代LoggedAction的列表,并通过虚拟继承获取特定的子行为。但是,这不适用于使用Django模型。

示例models.py

class LoggedAction(models.Model):
    user = models.ForeignKey(User)
    timestamp = models.DateTimeField(auto_now_add=True)

    def __unicode__(self):
        return "%s: %s %s" % (unicode(self.timestamp), unicode(self.user), unicode(self.action()))

    def action(self):
        return ""

class LoginAction(LoggedAction):
    def action(self):
        return "logged in"

class LogoutAction(LoggedAction):
    def action(self):
        return "logged out"

然后我想[unicode(l) for l in LoggedAction.objects.all()]并获取u'2012-02-18 18:47:09.105840: knatten logged in'等消息列表。

正如预期的那样,这不起作用,因为我从all()得到的是LoggedAction个对象的列表,其中包含loginaction成员或logoutaction成员。 (输出是u'2012-02-18 18:47:09.105840: knatten之类的消息列表,没有提及操作。)

是否有理智的方式来获取我所追求的行为,或者我是否尝试在此处应用错误的范例? (我想我是,我应该在LoggedAction

中作为成员采取具体行动

2 个答案:

答案 0 :(得分:2)

是的,这可能是错误的范例。很容易被对象关系映射器(ORM)误导 - 数据库表并没有真正将所有这些映射到对象,这种差异被称为object-relational impedance mismatch

你真正需要的是让action成为一个领域。此字段可以采用choices参数来表示该字段的可能值 - 即登录或注销:

class LoggedAction(models.Model):
    ACTIONS = (
       ('I', 'logged in'),
       ('O', 'logged out')
    )
    user = models.ForeignKey(User)
    timestamp = models.DateTimeField(auto_now_add=True)
    action = models.CharField(max_length=1, choices=ACTIONS)

    def __unicode__(self):
        return u"%s: %s %s" % (self.timestamp, self.user, self.get_action_display())

请注意,我使用了任意单字符字符串来表示操作,并使用get_action_display()魔术方法来获取完整描述。

答案 1 :(得分:1)

从django-model-utils查看InheritanceManager。它允许您获取具体的子类。