2016-10-19 44 views
0

我認爲這最好用一個例子來解釋。如何級聯一對多關係中的更新?

class GrandParent(models.Model): 
    pass 

class Parent(models.Model): 
    grandparent = models.ForeignKey(GrandParent, null=True, blank=True, default=None)  

class Child(models.Model): 
    parent = models.ForeignKey(Parent, null=True, blank=True, default=None) 
    grandparent = models.ForeignKey(GrandParent, null=True, blank=True, default=None)  

所以我們有三個類。孩子擁有父母和父母的外鍵,父母擁有外父母給外祖父母的外鍵。

在Django Admin區域中,我單擊父記錄(P1)並將其外鍵設置爲一個GrandParent記錄(GP1)。

我想這個級聯到所有的兒童記錄。換句話說,每個已經有P1外鍵的子記錄都應該自動獲得GP1的外鍵。

有沒有Django的方法來做到這一點?

謝謝。

+1

是否有一個原因,你想在你的數據庫中有冗餘數據?如果你的例子真的顯示了你想要做的事情,我會完全忽略來自Child模型的祖父母字段。 –

+0

是的,它是一個非常複雜的數據庫設計的分析產品。在設計時,性能等等之間存在權衡。 –

回答

1

我個人遠離從使用管理頁面,一旦你需要真正的商業邏輯,但這裏是答案:

如果你只需要從管理頁面做到這一點,你可以簡單地覆蓋管理員保存功能

class ParentAdmin(admin.ModelAdmin): 
    list_display = ('id', 'parent',) 

    def save_model(self, request, obj, form, change): 
     obj.save() 
     for c in obj.child_set.all(): 
      if c.granparent != obj.grandparent: 
       c.grandparent = obj.grandparent 
       c.save() 

admin.site.register(Parent, ParentAdmin) 

但是,如果你想確保孩子總是更新,無論誰做了保存(),您可以

1.-覆蓋模型的save()函數(但是這可能創造如果你的模型是循環依賴在不同的文件:

class Parent(models.Model): 
    grandparent = models.ForeignKey(GrandParent, null=True, blank=True, default=None) 

    def save(self, *args, **kwargs): 
     for c in self.child_set.all(): 
      if c.granparent != self.grandparent: 
       c.grandparent = self.grandparent 
       c.save() 
     super(Parent, self).save(*args, **kwargs) 

2:爲了避免循環依賴,你可以使用一個信號捕捉保存並就此採取行動

from django.db.models.signals import post_save 
from django.dispatch import receiver 

class Child(models.Model): 
    parent = models.ForeignKey(Parent, null=True, blank=True, default=None) 
    grandparent = models.ForeignKey(GrandParent, null=True, blank=True, default=None) 

@receiver(post_save, sender=Parent) 
def post_save_parent_callback(sender, **kwargs): 
    parent = kwargs['instance'] 
    for c in parent.child_set.all(): 
     if c.granparent != parent.grandparent: 
      c.grandparent = parent.grandparent 
      c.save() 

希望這有助於。

+0

很多消化。非常感謝您花時間幫助我! –