3

我想记录用户所做的操作。在大多数 OO 语言中,我会通过一个LoggedAction类来实现这一点,它有几个子类,例如LoginActionLogoutAction. 然后我可以遍历一个 LoggedActions 列表并通过虚拟继承获得特定的子行为。但是,这不适用于 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()的对象列表。(输出是一个消息列表,如,没有提及操作。)LoggedActionloginactionlogoutactionu'2012-02-18 18:47:09.105840: knatten

有没有一种理智的方法来获得我所追求的行为,或者我是否试图在这里应用错误的范例?(我想我是,我应该只是作为成员的具体行动LoggedAction

4

2 回答 2

2

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

您真正需要的是制作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()魔术方法来获取完整描述。

于 2012-02-18T22:46:14.813 回答
1

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

于 2012-02-18T22:05:19.860 回答