如何向 Django QuerySet 添加附加列

Posted

技术标签:

【中文标题】如何向 Django QuerySet 添加附加列【英文标题】:How to add additional column to Django QuerySet 【发布时间】:2014-10-08 03:37:11 【问题描述】:

我有一个带有 Books 的 QuerySet,我想在每个 Book 结果中添加一个 score 字段。

qs = Book.objects.all()

在原始 SQL 中我会写:

SELECT
    *,
    (
        (SELECT COUNT(*) FROM votes WHERE value=1 AND book=b.id) - 
        (SELECT COUNT(*) FROM votes WHERE value=-1 AND book=b.id)
    ) AS score
FROM
    Book b;

如何在 Django 中实现它?我试过annotate(),但它似乎不适合这种东西。

【问题讨论】:

annotateextraselect 一起使用(在此处提问之前请更仔细地使用google)。 看看docs.djangoproject.com/en/dev/topics/db/aggregation/… 谷歌中没有一个页面可以描述我想要的。我已经在文档中阅读了有关 annotateextra 的所有内容。对此它只字未提。如果您设法找到任何有用的东西,请分享一个链接。 @ambi 如何在这里过滤任何帮助? 【参考方案1】:

原始 SQL 不是唯一的方法。您可以使用Value() 表达式(参见文档here):

from django.db.models import CharField, Value

MyModel.objects.all().annotate(mycolumn=Value('xxx', output_field=CharField()))

【讨论】:

太棒了,我正在找这个 给出错误:未为 output_field 定义全局名称“IntegerField” 您需要像往常一样导入IntegerField。【参考方案2】:

如果投票的可能值只有 1 和 -1,您可以使用提到的 annotate:Book.objects.annotate(score=Sum('votes__value')) 将它们相加。

如果有更多可能的值,您可以通过在上述查询中添加.filter(votes__value__range=(1,1)) 来过滤注释。

如果它更复杂,您将不得不使用 extraselect

【讨论】:

谢谢。添加另一列不能用于SumAvg 和类似的列怎么样?如果我们想添加一些格式化文本或布尔列怎么办? annotate(mycolumn='xxx') 不起作用。 您应该在这里使用extraselect,如下所述:docs.djangoproject.com/en/1.7/ref/models/querysets/#extra 所以,原始 SQL 是唯一的方法 :( 感谢您的帮助

以上是关于如何向 Django QuerySet 添加附加列的主要内容,如果未能解决你的问题,请参考以下文章

Django QuerySet:用于计数值出现的附加字段

如何使用附加过滤的相关对象作为 Django 中的字段来获取结果?

如何从 Django 中的 get_queryset 方法返回多个查询集对象或添加查询集结果

如何有效的遍历django的QuerySet

在 Django 中将 QuerySet 转换为 JSON

在 Django 中向序列化响应添加附加数据