2012-10-01 2 views
0

어떤 사이트에 어떤 제품이 표시되는지 쉽게 제어 할 수 있어야하며 많은 제품이 있으므로 카테고리, 제작자 및 태그를 통해 제품 사이트를 설정하고 싶습니다. 따라서 제품 OR (해당 카테고리와 제작자 및 태그 중 하나)이 사이트에 링크되어있는 경우 사이트에 제품을 표시합니다. 내가 get_sites 방법을 최적화하는 방법Django의 복잡한 다중 모델 쿼리 최적화

from django.db.models import Model, ManyToManyField, ForeignKey, BooleanField 

class Site(Model): 
    enabled = BooleanField() 

class Producer(Model): 
    sites = ManyToManyField(Site) 

class Category(Model): 
    sites = ManyToManyField(Site) 

class Tag(Model): 
    sites = ManyToManyField(Site) 

class Product(Model): 
    producer = ForeignKey(Producer) 
    category = ForeignKey(Category) 
    tags  = ManyToManyField(Tag) 
    sites = ManyToManyField(Site) 

    def get_site_ids(self): 
     if self.sites.exists(): 
      return list(self.sites.values_list('id', flat=True)) 
     else: 
      p = list(self.producer.sites.values_list('id', flat=True)) 
      c = list(self.category.sites.values_list('id', flat=True)) 
      t = sum([list(tag.sites.values_list('id', flat=True)) for tag in self.tags.all()], []) 
      ids = set.intersection(set(p), set(c), set(t)) 
      return ids 

내 질문은 : 내가 함께 결국 코드는 다음 (간체)인가? 일부 쿼리에 참여할 수 있습니까?


업데이트 : 나는 색인 생성되고 검색 엔진에 의해 저장되는 사이트 ID에만 관심이 있습니다.

답변

1

가능한 경우 데이터베이스 수준에서 수행하려는 모든 작업을 시도하고 수행해야합니다. 이 같은 것이 당신을 시작하게 할 것입니다.

from django.db.models import Sum 
self.objects.select_related("producer__sites", 
          "category__sites", 
          "tags__sites", 
          "sites").annotate(tag_count=Sum("tags__sites__id")) 

select_related 가득 생산자, 카테고리, 태그 및 사이트 참조로 Product 모델을 돌려줍니다. 여기에는 제작자, 카테고리 및 태그에 sites 참조가 포함되어 있습니다. 이렇게하면 Django가 데이터베이스에 쿼리하는 횟수가 줄어 듭니다.

annotate는 tags_의 사이트 거기에 _id를 합계를 가지고 tag_count라는 이름의 반환 Model 인스턴스에 속성을 추가합니다.

Django QuerySet Reference은 사용자가 반환하려는 정확한 특성을 알지 못하기 때문에 도움이 될 수 있습니다.

+0

감사합니다. 사이트 ID 만 있으면됩니다. – Andrei

+0

불행히도 Sum aggregator는 사이트 ID를 수집해야하므로 여기서는 도움이되지 않습니다. 더 많은 쿼리를 실행해야합니다 (예 : @pram에 언급 된'prefetch_related '와 함께). – Andrei

1

예. select_related 및/또는 prefetch_related을 사용하면 장고에서 쿼리 수를 줄일 수 있습니다.

그러나 select_related은 외래 키와 일대일 관계에서만 작동합니다. Product 모델에 ManyToMany가 있으므로 Product.get_sites()에서 쿼리를 줄이려면 prefetch_related을 사용해야합니다.