python - Django-从子查询中注释多个字段

标签 python django django-rest-framework django-orm

我正在处理一个Django项目,在该项目上我具有一个'A'对象的查询集(A.objects.all()),并且需要从'B'objects'子查询中注释多个字段。问题在于,注释方法只能针对每个参数处理一种字段类型(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,因此我需要使用Subquery为A.objects.all()中的每个A选择一个特定的B并使用OuterRefs和a将其附加到该A上。几个过滤器(我只想要B的几个字段),这对我来说是一个微不足道的问题。

感谢您的任何提前帮助!

最佳答案

在这种情况下,我要做的是使用prefetch-related

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个对象。

关于python - Django-从子查询中注释多个字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60910345/

相关文章:

python - 将程序中的 Python Pandas Dataframe 输出合并到一个 Dataframe 中

Django基于类的 View 函数执行顺序

django - 将客户端计算字段添加到 django admin

python-3.x - 在多对多字段中添加元素并保持顺序

python - 数据库优先 Django 模型

django - 如何从 Django 中的查询集中排除非事件用户

python - 在用户注册时发送密码,django-allauth

python - Spark 非确定性 Pandas UDF 会出现什么问题

python - 如何像访问 pandas 数据框一样快速访问 numpy 数组

python - 具有同一对象的多个 View 集和路由器的 Django Rest Framework