2017-12-14 9 views
5

モデルに数字を1対1の数多くの関係があるシステムがあります。モデルは他のモデルと1対1の関係を持っています(例えば1b - > 1c)。そのように描か:Djangoは1対1の関係で1対多を連鎖するためのクエリーセットを決定できません

/--- b1 --- c1 
/
a ---- b2 --- c2 
\ 
    \--- b3 --- c3 

は、私はそれがaに対応するすべてのc年代を集める方法を作成することが決定したんです。

私と同じ構造のモデルシステムがあれば、私が考え出すことのできる最良の方法が、方法:Person.find_important_treats()に示されています。

データベースへの呼び出しがあまり含まれていない方が良いでしょうか?

from django.db import models 

class Person(models.Model): 
    """ The 'a' from my above example """ 

    def find_important_treats(self): 
     return (pet.treat for pet in self.pets) 

class Pet(models.Model): 
    """ The 'b' from my above example """ 

    owner = models.ForeignKey(
     to=Person, 
     related_name='pets' 
    ) 

    favourite_treat = models.ForeignKey(
     to=Treat, 
    ) 

class Treat(models.Model): 
    """ The 'c' from my above example """ 
    pass 
+1

です。 – aquaman

+1

もっと具体的にすることができますか、治療対象全体に絡み合っているのか、治療IDを突き止めますか?それは大きな違いになります! – DhiaTN

+0

@DhiaTN、テンプレートにレンダリングしたい情報があるので、私は全体の欲望(貪欲な私)をしたい。 – Splatmistro

答えて

4

私はあなたのユースケースに応じて2つのほぼ同様のソリューションを提案:

  • キャッシュを使用せずに、キャッシュ
class Person(models.Model): 
     """ The 'a' from my above example """ 

     @property 
     def iter_important_treats(self): 
      return (pet.treat_id for pet in self.pets.all()) # will use the cached objects if they exist 

    person = Person.objects.get(id=person_id).select_related('pets') # to cache the pets list within the person object avoiding future additional queries 
    treats = Treat.objects.filter(id__in=person.iter_importent_treats) 
  • を使用する:
class Person(models.Model): 
     """ The 'a' from my above example """ 

     @property 
     def iter_important_treats(self): 
      return iter(self.pets.values_list('treat_id', flat=True)) # caching will not affect the query behviour 

    person = Person.objects.get(id=person_id) 
    treats = Treat.objects.filter(id__in=person.iter_importent_treats) 

NB:

  1. 私たちはDjangoはペット・オブジェクト・レベルですでにtreat_idが保存されますが、あなたはtreat__idを使用する場合は、あなたが参加するクエリを強制するために、追加の参加のクエリを避けるためにtreat__id代わりtreat_idを使用しています。
  2. IDのイテレータにプロパティを制限 ``あなたはTreat.objects.filter(pet__owner__pk = PERSONID)答えを見つけるでしょう、これらの線に沿っている可能性があり、単に可逆性と保守性ため
2

次はあなたが後にしている何をすべき:それはペットが持っていることをTreat秒のidsの全てを取得し、それらを返す

def find_important_treats(self): 
    return Treat.objects.filter(id__in=person.pets.values_list('treat_id')) 

関連する問題