如何在Django中结合annotate与prefetch_related限制查询结果?
错误原因
你使用[100]对QuerySet进行索引时,会直接取出单个Question实例(对应第101条数据,索引从0开始),而prefetch_related是QuerySet专属方法,单个模型对象没有这个属性,因此触发'Question' object has no attribute 'prefetch_related'错误。
正确实现方式
要限制查询结果为100条,需使用切片语法[:100](返回包含前100条数据的QuerySet),而非单个元素索引。所有QuerySet方法(包括prefetch_related)可在切片之前调用,或把切片放在链式调用的最后(Django QuerySet是惰性执行的,顺序不影响最终查询性能)。
正确代码示例:
all_questions = Question.objects.all().annotate( is_complete=Case( When(pk__in=completed_questions.values('pk'), then=Value(True)), default=Value(False), output_field=BooleanField() ), votes_difference=Count('like') - Count('unlike'), ).order_by('votes_difference').prefetch_related('tags')[:100]
如果需要获取某一段范围的数据(比如第100到200条),同样使用切片语法:
all_questions = Question.objects.all().annotate( # 省略annotate内容 ).order_by('votes_difference').prefetch_related('tags')[100:200]
补充说明
Django QuerySet的惰性特性意味着:所有链式调用(annotate、order_by、prefetch_related、切片)都只是构建查询语句,直到你实际遍历数据(比如循环、转换为列表)时才会执行数据库查询,因此不用担心顺序导致的性能问题。
内容的提问来源于stack exchange,提问作者Gagan
相关产品推荐
相关产品推荐

