我正在处理一个Django项目,在该项目上我具有一个“ A”对象(A.objects.all()
)的查询集,并且需要注释来自“ B”对象“子查询的多个字段。问题在于,注释方法只能针对每个参数处理一种字段类型(DecimalField,CharField等),因此,要注释多个字段,我必须使用类似以下内容的方法:
A.objects.all().annotate(b_id =Subquery(B_queryset.values('id')[:1],
b_name =Subquery(B_queryset.values('name')[:1],
b_other_field =Subquery(B_queryset.values('other_field')[:1],
... )
这是非常低效的,因为它会在最终SQL上为我要注释的每个字段创建一个新的子查询/子选择。我想在其values()参数的多个字段上使用相同的Subselect,并在A的queryset上全部注释它们。我想使用这样的东西:
b_subquery = Subquery(B_queryset.values('id', 'name', 'other_field', ...)[:1])
A.objects.all().annotate(b=b_subquery)
但是,当我尝试执行此操作(并访问第一个元素A.objects.all().annotate(b=b_subquery)[0]
)时,将引发异常:
{FieldError}Expression contains mixed types. You must set output_field.
如果我设置了Subquery(B_quer...[:1], output_field=ForeignKey(B, models.DO_NOTHING))
,我得到一个数据库异常:
{ProgrammingError}subquery must return only one column
简而言之,整个问题是我有多个“属于”一个A的B,所以我需要A.objects.all()
使用Subquery对每个A中的一个选择一个特定的B并将其附加到该A上,并使用OuterRefs和一些过滤器(我只想要B的几个字段),这对我来说是一个微不足道的问题。
感谢您的任何帮助!
在这种情况下,我要做的是使用与预取相关的
a_qs = A.objects.all().prefetch_related(
models.Prefetch('b_set',
# NOTE: no need to filter with OuterRef (it wont work anyway)
# Django automatically filter and matches B objects to A
queryset=B_queryset,
to_attr='b_records'
)
)
现在a.b_records
将是一个包含a's
相关b
对象的列表。根据您过滤的方式,B_queryset
此列表可能仅限于1个对象。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句