2016-10-19 9 views
0

私はこれが一例でもっとも説明されていると思います。1対多の関係で更新をカスケードする方法はありますか?

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)  

私たちは3つのクラスを持っています。子は親とGrandParentに外部キーを持ち、ParentはGrandParentに外部キーを持っています。

Django管理領域では、親レコード(P1)をクリックして、その外部キーをGrandParentレコード(GP1)に設定します。

私はこれをすべての子レコードにカスケードしたいと思います。言い換えれば、すでにP1への外部キーを持っているすべての子レコードは自動的にGP1に外部キーを取得するはずです。

これを行うにはDjangoの方法はありますか?

ありがとうございます。あなたが唯一の管理ページからこれを実行する必要がある場合は

、あなたは、単に管理機能を上書き保存することができます

+1

データベースに冗長なデータが必要な理由はありますか?あなたの例が本当にあなたがしたいことを示している場合、私は子モデルから完全に祖父母フィールドを除外します。 –

+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

そこにはたくさんのダイジェストがあります。私を助けるために時間を割いてくれてありがとう! –

関連する問題