2017-12-14 14 views
5

모델에 숫자가 1 : 1 -> 많은 b 인 다 대 일 관계와 그 모델은 다른 모델과 일대일 관계를 맺고 있습니다 (예 : 1b -> 1c). 과 같이 그린 :Django는 일대일 관계로 일대 다 체인을 연결하기위한 쿼리 세트를 결정할 수 없습니다.

/--- 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

당신이 답'Treat.objects.filter (pet__owner__pk = personId)를'발견 할 것이다 이러한 라인을 따라 할 수 가역성 및 유지 관리를 위해서입니다. – aquaman

+1

좀 더 구체적으로 할 수 있습니까? 전체 치료 대상에 개입했거나 치료 ID를 진술 할 수 있습니까? 그것은 큰 차이를 만든다! – DhiaTN

+0

@DhiaTN, 템플릿에 렌더링하려는 정보가 있으므로 전체 치료 (욕심이 많다)를 원합니다. – Splatmistro

답변

4

내가 사용 사례에 따라이 거의 유사한 솔루션을 제안

NB : 장고는 애완 동물 개체 수준에서 이미 treat_id 저장하기 때문에

  1. 우리가 쿼리에 가입 추가 피하기 위해 대신 treat__idtreat_id를 사용하지만 treat__id를 사용하는 경우 다음 조인 쿼리를 강제로. ID의 반복자에 속성을 제한
  2. 단지
2

다음은 당신이 후에 어떤 수행해야합니다

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

그것은 Treat의 애완 동물이 있는지의 ids을 모두 획득 한 다음를 반환합니다.

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) 
: 캐싱을 사용하지 않고

  • 사용하여 캐싱
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) 
  • :