2012-02-18 95 views
3

我想記錄用戶所做的動作。在大多數OO語言中,我將通過LoggedAction類實現此功能,其中有幾個子類,如LoginActionLogoutAction。然後我可以遍歷一個列表LoggedAction s,並通過虛擬繼承來獲取特定的子行爲。但是,這不適用於使用Django模型。有沒有在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()得到的是具有或者一個loginaction成員或成員logoutaction對象LoggedAction的列表。 (輸出是一樣u'2012-02-18 18:47:09.105840: knatten消息列表,沒有提到的動作。)

是否有一個健全的方式拿到後,我的行爲,還是我想在這裏應用錯誤的範例? (我想我是,我應該只是作爲LoggedAction成員的具體行動)

+0

認識到,正如您在此處顯示的那樣,它將在數據庫中以三個表的形式實現,其中LoginAction和LogoutAction加入到公共表中,並且可以實例化LoggedAction對象。您可能想要使LoggedAction抽象。 – 2012-02-18 22:11:53

+0

@ChrisMorgan如果我使'LoggedAction'抽象,我無法迭代它們,對吧?所以特別是'LoggedAction.objects.all()'將不可能? – knatten 2012-02-18 22:15:06

+0

不確定;事實上,我從來沒有理由用一個子類迭代模型。 – 2012-02-18 22:20:32

回答

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()魔術方法來獲得完整的描述。

+0

是的,期望能夠在關係數據庫上打擊完整的OO可能有點樂觀。 我希望能夠在子類中存儲一些額外的信息,但它們可能都是'TextField'。所以我想我可以使用你的解決方案,在LoggedAction類中使用'TextField'。 – knatten 2012-02-19 11:37:36

1

看看來自django-model-utils的InheritanceManager。它可以讓你獲得具體的子類。