我想记录用户所做的操作。在大多数OO语言中,我将通过LoggedAction
类实现此功能,具有多个子类,如LoginAction
和LogoutAction
。然后,我可以迭代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
)
答案 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
。它允许您获取具体的子类。