2011-09-10 55 views
4

我有以下型號:外鍵並保存方法在Django

class A: 
    b = ForeignKey('B') 

class B: 
    a = ForeignKey('A', null=True) 

我有幾種方法,解碼JSON對象和創建對象A和B. 假設的樹我有類型的對象一,我要保存,我試圖寫在A級這樣的事情

B中
def save(self, *args, **kwargs): 
    self.b.save() 
    super(A, self).save(*args, **kwargs) 

def save(self, *args, **kwargs): 
    if self.a: 
    self.a.save() 
    super(B, self).save(*args, **kwargs) 

雖然Ab和Ba在調用save()時分配了一個id,但它仍然違反了A中的非空約束。我讀過某處,這是由於ORM的工作原理,以及如何以某種方式緩存對象。

提出的解決辦法是做這樣的事情:

a = A() 
b = B() 
b.save() 
a.b = b 
a.save() 

但遞歸的原因很明顯,這不是在我的情況適合。所以圍繞我可以想到的唯一工作就是爲每個對象提供一個遞歸檢索每個需要保存的對象的方法,然後執行for循環以正確的順序保存每個對象。我真的想避免這種情況,因爲實際模型當然更復雜,涉及兩個以上的類和每個類多個外鍵。

所以我想我的問題很簡單:在這種情況下有沒有更好的方法或更常見的方法?

回答

2

經過一番靈魂搜索後,我發現這確實是一個緩存「問題」。我沒有時間去查看django代碼來了解事情是如何運作的,所以如果有人有一些有趣的見解,那將是非常棒的。

在此期間,我找到了解決辦法是強制對象清除其高速緩存是這樣的:

def save(self, *args, **kwargs): 
    self.b.save() 
    self.b = self.b # yes ... 
    super(A, self).save(*args, **kwargs) 

這並不工作,但對於這裏的記錄是一個小幫手,自動清除緩存之前的任何節能:

def clear_cache(obj): 
    map(lambda x: obj.__setattr__(x, obj.__getattribute__(x)), \ # force reassignment 
    map(lambda x: re.match('_(.*)_cache', x).groups()[0], \ # get attribute name 
    filter(lambda x: x.find('_cache') != -1, dir(obj))))  # get all attribute with cache 

@receiver(pre_save) 
def cache_callback(sender, instance, **kwargs): 
    clear_cache(instance) 
0

值得注意的是,您在調用超類保存方法之前,正在保存其他對象之前的,這可能與您想要的相反。

另外,這可能會變得更乾淨,請使用post-save signals

+0

那麼這取決於哪個對象救人第一,實際上在我的情況都可能發生,但如果我可以解決這一個將是巨大的。 – gobadiah

+0

Oups enter發送了評論... 這是正確的順序,因爲當我保存A時,我希望外鍵有效,因此我必須先保存它。所以在我的情況下,我應該使用預先保存的信號,我嘗試過,它仍然給我非空約束錯誤。 – gobadiah