Python 在Django模型中有没有一种合理的方法来模拟虚拟继承?
我想记录用户所做的操作。在大多数OO语言中,我会通过一个Python 在Django模型中有没有一种合理的方法来模拟虚拟继承?,python,django,oop,inheritance,virtual-inheritance,Python,Django,Oop,Inheritance,Virtual Inheritance,我想记录用户所做的操作。在大多数OO语言中,我会通过一个LoggedAction类来实现这一点,它有几个子类,如LoginAction和LogoutAction。然后,我可以遍历LoggedActions列表,并通过虚拟继承获得特定的子行为。但是,使用Django模型时,这不起作用 示例models.py: class LoggedAction(models.Model): user = models.ForeignKey(User) timestamp = models.Dat
LoggedAction
类来实现这一点,它有几个子类,如LoginAction
和LogoutAction
。然后,我可以遍历LoggedAction
s列表,并通过虚拟继承获得特定的子行为。但是,使用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"
然后我想在LoggedAction.objects.all()中对l执行[unicode(l)for l
,并获得一个消息列表,如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
中作为一名成员执行特定操作)看看django model UTIL。它允许您获得具体的子类。是的,这可能是错误的范例。很容易被对象关系映射器(ORM)误导——数据库表并没有很好地映射到对象,这种差异被称为
您实际需要的是将操作
设置为一个字段。此字段可以采用表示该字段可能值的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\u action\u display()
magic方法来获得完整的描述。请注意,正如您在这里所示,它将在数据库中作为三个表实现,LoginAction和LogoAction连接在一个公共表上,并且可以实例化LoggedAction对象。您可能想将LoggedAction抽象化。@ChrisMorgan如果我将LoggedAction
抽象化,我将无法对它们进行迭代,对吗?所以特别是LoggedAction.objects.all()
将是不可能的?不确定;事实上,我从来没有理由用子类迭代一个模型。是的,期望能够在关系数据库上实现完整的OO可能有点乐观。我希望能够在子类中存储一些额外的信息,但它们可能都是TextField
。因此,我想我可以使用您的解决方案,在LoggedAction
类中设置TextField
。