2016-10-19 97 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

很多消化。非常感谢您花时间帮助我! –