2015-10-06 34 views
4

说我已经有了与标签对象的多元关系的图像对象。我如何限制Django中的prefetch_related?

现在,我正在创建一个搜索视图来显示图像,并为每个图像显示标签,显然,要做的事情就是预取图像的标签。

但是我每次只显示15张图像,但我必须评估整个查询集以显示总体结果数。 所以我需要切片之前预取标签为第15个元素

如果我预取标签:

images = watson.filter(queryset, query).prefetch_related('tags') 
amount = images.count() 
images = images[:15] 

这是非常糟糕的,因为可以有成千上万的结果和各结果可以有很多标签。

,但如果我先切片:

images = watson.filter(queryset, query).prefetch_related('tags')[:15] 
amount = images.count() 

现在我只预取15分的结果,这是很好,但是我不能不做另一个查询统计结果标签。

如果我这样做:

images = watson.filter(queryset, query) 
amount = len(images) 
images = images.prefetch_related('tags')[:15] 

我还是最终击中数据库两次,因为预取做一个新的数据库查询。

基本上我需要打一次数据库获得的所有图像,而只预取标签的第一个15

回答

1

尝试调用count()第一,然后做prefetch_related()和切片查询集。

images = watson.filter(queryset, query) 
amount = images.count() 
images = images.prefetch_related('tags')[:15] 

这将执行一个计数查询,一个查询前15个图像,一个查询标签。调用count()len()好,因为它不会获取不需要的图像。

+0

本示例将数据库命中两次,一次调用count并再次调用prefetch_related时。 – davegri

+0

'count()'导致性能不佳?如果不是,我认为担心这是一个过早优化的例子。我不确定是否提取所有结果,并且仅预取前15个将显着加快;对于大型查询,调用'count()'比'len()'更有效,因为queryset没有加载到内存中。 – Alasdair

+0

因为我不能仅仅预取15次,所以不得不为一组图像命中数据库。为什么这是过早的优化?我期待优化..使用计数,而不是len()是一个有效的更正,但多数民众赞成在这个问题不是什么 – davegri