对于名为QuerySet
的模型,我具有以下自定义Program
方法:
def with_volunteer_stats(self):
from programs.models import Session
volunteers_needed = ExpressionWrapper(
F('num_student_seats') / F('student_volunteer_ratio'),
output_field=models.IntegerField())
sessions = (
Session.objects.filter(program_id=OuterRef('pk'))
.annotate(num_volunteers=Count('volunteer_attendances__volunteer', distinct=True))
.order_by('num_volunteers')
)
qs = self.annotate(
volunteers_needed=volunteers_needed,
least_volunteers=Subquery(sessions.values('num_volunteers')[0])
).annotate(
remaining_volunteers_needed=(F('volunteers_needed') - F('num_volunteers'))
)
return qs
运行此程序时,出现异常:
ValueError: This queryset contains a reference to an outer query and may only be used in a subquery.
回溯显示使用Subquery
对行进行评估时发生的异常。这与Django文档中有关如何使用Subquery
的示例非常接近。有什么想法我做错了吗?
答案 0 :(得分:0)
我遇到了同样的问题。现在我有了一个更好的主意,我想为后代添加一个解释。
问题似乎在这里:
Subquery(sessions.values('num_volunteers')[0])
# ^^^
目的是为子查询提供QuerySet,但实际上发生的是项目访问器过早强制执行评估。换句话说,这将产生一个QuerySet:
sessions.values('num_volunteers')
但这迫使评估产生一个对象:
sessions.values('num_volunteers')[0]
这意味着sessions.values('num_volunteers')
QuerySet在子查询的上下文之外进行评估。因此,如果不清楚,则错误消息是正确的。
根据以下mfrackowiak的评论,Django文档提供了有关如何limit the subquery to a single row的建议:
sessions.values('num_volunteers')[:1]