Django 中带有多个结果的子查询的注释

Ale*_*cer 0 django django-orm django-postgresql django-annotate django-subquery

我在我的项目中使用了 postgresql 数据库,我使用了 django文档中的以下示例。

from django.db.models import OuterRef, Subquery
newest = Comment.objects.filter(post=OuterRef('pk')).order_by('-created_at')
Post.objects.annotate(newest_commenter_email=Subquery(newest.values('email')[:1]))
Run Code Online (Sandbox Code Playgroud)

但不是最新的评论者电子邮件,我需要最后两封评论者的电子邮件。我改变了[:1][:2],但此异常引发:ProgrammingError: more than one row returned by a subquery used as an expression

Mat*_*kel 5

您需要以某种方式聚合子查询结果:也许通过使用ARRAY()构造。

您可以创建一个子类Subquery来执行此操作:

class Array(Subquery):
    template = 'ARRAY(%(subquery)s)`
    output_field = ArrayField(base_field=models.TextField())
Run Code Online (Sandbox Code Playgroud)

(您可以使用更自动的方法来获取输出字段,但这现在应该对您有用:有关更多详细信息,请参阅https://schinckel.net/2019/07/30/subquery-and-subclasses/)。

然后你可以使用:

posts = Post.objects.annotate(
    newest_commenters=Array(newest.values('email')[:2]),
)
Run Code Online (Sandbox Code Playgroud)

发生这种情况的原因是 postgres 中的相关子查询可能只返回一行,一列。您可以使用这种机制来处理多行,如果需要多列,也可以使用 JSONB 构造。