Django子查询和带有OuterRef的注释

Django子查询和带有OuterRef的注释,django,django-subquery,Django,Django Subquery,在Django 1.11子查询中,将annotate()与OuterRef一起使用时遇到问题。示例模型: class A(models.Model): name = models.CharField(max_length=50) class B(models.Model): a = models.ForeignKey(A) 现在,一个带有子查询的查询(这没有任何意义,但说明了我的问题): 这会产生以下错误: Traceback (most recent call last)

在Django 1.11子查询中,将annotate()与
OuterRef
一起使用时遇到问题。示例模型:

class A(models.Model):
    name = models.CharField(max_length=50)


class B(models.Model):
    a = models.ForeignKey(A)
现在,一个带有子查询的查询(这没有任何意义,但说明了我的问题):

这会产生以下错误:

Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "myapp/models.py", line 25, in a
    n=OuterRef('name')
  File ".virtualenv/lib/python2.7/site-packages/django/db/models/query.py", line 948, in annotate
    if alias in annotations and annotation.contains_aggregate:
AttributeError: 'ResolvedOuterRef' object has no attribute 'contains_aggregate'
更改
OuterRef
以使用自定义表达式

A.objects.all().annotate(
    s=Subquery(
        B.objects.all().annotate(
            n=RawCol(A, 'name')
        ).values('n')[:1],
        output_field=CharField()
    )
)
屈服

SELECT "myapp_a"."id",
       "myapp_a"."name",

  (SELECT "myapp_a"."name" AS "n"
   FROM "myapp_b" U0 LIMIT 1) AS "s"
FROM "myapp_a"

对于A的每一行,B的一个相关行的一个字段可以通过这种方式进行注释

subq=Subquery(B.objects.filter(a=OuterRef('pk')).order_by().values('u B')[:1])
qs=A.objects.all().注释(b_字段=subq)
(将其编写为两个带有临时变量的命令更具可读性。这是一种类似于文档的样式。)

它被编译为一个SQL请求:

>>> print(str(qs.suery))
SELECT a.id, a.name,
  (SELECT U0.any_field_of_b FROM b U0 WHERE U0.a_id = (a.id)  LIMIT 1) AS b_field
FROM a

(简化,不带“appname”)

这是Django中的一个已知错误,已在3.0中修复

有关讨论,请参阅

如果您像我一样需要对字段进行注释,以便在以下子查询中使用它,请记住,您可以像这样堆叠
OuterRef


id\uuu in=子查询(
MyModel.objects.filter(
字段=OuterRef(OuterRef(某些外部字段))
)
)

请参阅。无法理解此处的用例。@SHIVAMJINDAL在问题中说,没有用例。他只是提供了一个例子。你应该把OuterRef放在
.filter(a=OuterRef('pk'))
中,然后做注释
SELECT "myapp_a"."id",
       "myapp_a"."name",

  (SELECT "myapp_a"."name" AS "n"
   FROM "myapp_b" U0 LIMIT 1) AS "s"
FROM "myapp_a"
>>> print(str(qs.suery))
SELECT a.id, a.name,
  (SELECT U0.any_field_of_b FROM b U0 WHERE U0.a_id = (a.id)  LIMIT 1) AS b_field
FROM a