我将发布一些不完整的代码,以使示例变得简单。我正在运行递归函数来计算层次结构上的一些指标。
类别类别(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之后不喜欢它们一样!)我可以运行一次查询并将其传递下来。
根据我对Django的查询集的理解,它们不会在我的if queryset == None然后queryset = stuff部分进行评估。我怎么强迫这个?当我做metric_queryset.filter(category=self)
之类的事情时会重新评估吗?
我不关心数据的新鲜度。我只想从数据库中读取一次指标和评级,然后在以后过滤它们而不再次访问数据库。这是一个令人沮丧的问题,感觉应该有一个非常简单的答案。酸洗看起来可以起作用,但在Django文档中没有很好地解释。
答案 0 :(得分:3)
我认为这里的问题是你在递归调用之前没有评估查询集。如果您使用list()
强制评估查询集,那么它应该只访问数据库一次。请注意,您必须将metrics_in_cat
行更改为python级别过滤器,而不是使用查询集过滤器。
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