2017-12-11 8 views
0

アカウント、会社、製品の3つのモデルがあります。製品には、会社、会社、FKに対するForeignKeyがあります。 すべてに 'is_active'というフィールドがあります。モデルの更新時に逆の外部キーモデルを更新します

私は必要なもの
class Product(Meta): 
    company = models.ForeignKey(Company, related_name='products', on_delete=models.CASCADE) 
    is_active = models.BooleanField(default=False) 


class Company(Meta): 
    account = models.ForeignKey(Account, related_name='account', on_delete=models.CASCADE) 
    is_active = models.BooleanField(default=False) 

  1. アカウントis_activeは、私は、関連するすべての企業のためにしたいFalseになった場合、当社のis_activeは、私が会社に関連するすべての製品に必要偽
  2. 偽になるis_activeなり、アカウントに、is_activeは偽になるために、また、製品

に伝播私は、保存(または使用後のセーブ信号)を変更する必要があることを知っているが、私は外部キーモデルを選択して変更する方法を知らず、複数のレベルを伝播する。

この関係は親から子へと逆であり、子から親へは逆である。、フィールドFKは使用できません。

+0

逆リレーションのインスタンスは、' MODEL_set'でアクセスできます。 Companyインスタンスの場合は、 'company_instance.product_set'ですべての製品にアクセスできます。これはあなたの質問に答えますか? https://docs.djangoproject.com/en/2/0/topics/db/queries/#related-objects – petr

+0

@petrデフォルトの代わりに関連する名前を使用できますが、逆FKであるため、それらをループする必要があります子モデルのセーブ/アップデートを行います。アカウントがさらに繁殖した場合、いくつかのものを試しますが、動作しません。おそらくあなたは私に完全な質問の例を与えることができます – user3541631

+0

あなたはさらに進んでいく必要はありません - 両方のモデルは 'save()'メソッドをオーバーライドします。つまり、ある関係を離れてインスタンスを変更すると、自動的に。 – petr

答えて

1

私の解決方法を教えてください。まず、フィールドの変更(この場合は "is_active")を追跡する必要があります。モデルののinitでこれを行うには、キャッシュされた値を保持しなければならず、保存上の値をチェックする必要があります:(アカウントの変更コードを追加します) I

class Company(Meta): 
    ...(field definitions) 

    def __init__(self, *a, **kw): 
     super().__init__(*a, **kw): 
     self.__original_is_active = self.is_active 

    def save(self, *a, **kw): 
     if self.__original_is_active != self.is_active and self.is_active==False: 
      # use raw update to perform better than loop 
      self.products.update(is_active=False) 
     super().save(*a, **kw) 

UPDATE:変更された場合、その後、DBを更新します(同社のモデルはあなたがself.company_set.all()self.companies.allするを変更後、保存方法では、会社への口座から多対多の関係を持っている場合、アカウント

class Account(Meta): 
    ...(field definitions) 

    def __init__(self, *a, **kw): 
     super().__init__(self, *a, **kw) 
     self.__original_is_active = self.is_active 

    def save(self, *a, **kw): 
     if self.__original_is_active != self.is_active and self.is_active == False: 
      for company in self.company_set.all(): 
       company.is_active = False 
       company.save() 
     super().save(*a, **kw) 

にForeignKeyの関係を持っていると仮定)それがすべてです。

アカウントモデルも同様ですが、 "update"メソッドはSQLを直接実行し、 "initを無視して保存するため、forループを使用して会社を更新するのを忘れないでください。 "私が会社で行ったこと(docsと言う)

+0

ありがとうございますので、アカウントの場合は、forループを使用するために "self.companies.update(is_active = False)"を使用するのではなく、場合によっては、ただ1社だけが仕事を更新するでしょうか? – user3541631

+0

update()メソッドを使用していません。外部キーに関連するオブジェクトのsaveメソッドは呼び出されません。同じことを言うdocs(https://docs.djangoproject.com/en/2.0/topics/db/queries/#updating-multiple-objects-at-once)を見てください。だからあなたが持っている外来キー関連のオブジェクトがいくつあるのかは関係ありません。forループ(また私の答えを更新しました)を使用しなければなりません –

+0

forループの例を追加してください、私は何か試しましたが、 – user3541631

関連する問題