2009-08-28 6 views
1

예제를 간단하게 만들기 위해 불완전한 코드를 게시 할 것입니다. 계층 적 구조에 대한 일부 메트릭을 계산하는 재귀 함수를 실행하고 있습니다.쿼리 세트 캐싱 및 재평가

클래스 카테고리 (models.Model) :

parent = models.ForeignKey('self', null=True, blank=True, related_name='children', default=1) 

def compute_metrics(self, shop_object, metric_queryset=None, rating_queryset=None) 
    if(metric_queryset == None): 
     metric_queryset = Metric.objects.all() 
    if(rating_queryset == None): 
     rating_queryset = Rating.objects.filter(shop_object=shop_object) 

    for child in self.children.all(): 
     do stuff 
     child_score = child.compute_metrics(shop_object, metric_queryset, rating_queryset) 

    metrics_in_cat = metric_queryset.filter(category=self) 
    for metric in metrics_in_cat 
      do stuff 

은 그게 무슨 일이 일어나고 있는지 볼 정도로 코드를 바랍니다. 필자가 여기서 한 것은 각 쿼리를 한 번 실행 한 다음 결과를 전달하는 재귀 함수입니다. 그것은 지금 일어나고있는 것처럼 보이지 않으며 그것은 성과를 죽이는 것입니다. 이 PHP/MySQL은 (내가 장고로 작업 한 후에 싫어하는만큼!) 쿼리를 한 번 실행 한 다음 전달할 수있었습니다.

Django의 querysets에 대해 이해 한대로, 그들은 if queryset에서 평가하지 않을 것입니다. == None then queryset = stuff 부분. 강제로 어떻게 할 수 있습니까? metric_queryset.filter(category=self) 일을 할 때 재평가됩니까?

데이터 최신 정보는 신경 쓰지 않습니다. 나는 단지 각각의 메트릭과 등급에 대해 한번 DB에서 읽으 려하고 나중에 DB를 다시 치지 않고 필터를 사용하기를 원합니다. 매우 간단한 대답이 있어야하는 것처럼 느껴지는 좌절스러운 문제입니다. pickling은 작동하는 것처럼 보이지만 Django 문서에서는 잘 설명되지 않습니다.

답변

3

여기 문제는 재귀 호출 후까지 쿼리 세트를 평가하지 않는다고 생각합니다. list()을 사용하여 쿼리 세트의 평가를 강제하면 데이터베이스에 한 번만 도달해야합니다. 유의하십시오. metrics_in_cat 행을 queryset 필터 대신 파이썬 레벨 필터로 변경해야합니다.

parent = models.ForeignKey('self', null=True, blank=True, related_name='children', default=1) 

def compute_metrics(self, shop_object, metric_queryset=None, rating_queryset=None) 
    if(metric_queryset is None): 
     metric_queryset = list([Metric.objects.all()) 
    if(rating_queryset is None): 
     rating_queryset = list(Rating.objects.filter(shop_object=shop_object)) 

    for child in self.children.all(): 
     # do stuff 
     child_score = child.compute_metrics(shop_object, metric_queryset, rating_queryset) 

    # metrics_in_cat = metric_queryset.filter(category=self) 
    metrics_in_cat = [m for m in metric_queryset if m.category==self] 
    for metric in metrics_in_cat 
     # do stuff