7

我有以下查询

a = Mainfee.objects.values('collected_by__username').
                       distinct().annotate(Sum('amount'))

结果看起来像这样

[{'collected_by__username': u'maindesk', 'amount__sum': 800}]

如何将第一个键a和第二个键重命名为b

我尝试了以下

m = Mainfee.objects.extra(select = 
   {'a':'collected_by__username'}).values('a').distinct().
    annotate(Sum('amount'))

并收到了这个

DatabaseError: no such column: collected_by__username

我也试过

m = Mainfee.objects.extra(select = 
   {'a':'collected_by__username'}).values('collected_by__username').distinct().
    annotate(Sum('amount'))

并得到

[{'collected_by__username': u'maindesk', 'amount__sum': 800}]

PS:我也想重命名第二个字段

4

4 回答 4

13

您可以使用关键字参数更改注释值的字典键:

m = Mainfee.objects.values('collected_by__username').annotate(b=Sum('amount'))

[{'collected_by__username': u'maindesk', 'b': 800}]

但是,没有快速简便的方法来重命名相关字段。你可以在 Python 中转换它,但你必须问问自己这是否真的有必要:

m = Mainfee.objects.values('collected_by__username').annotate(b=Sum('amount'))
m = [{'a': x['collected_by__username'], 'b': x['b']} for x in m]

或者这可能会稍微快一点:

m = Mainfee.objects.values_list('collected_by__username').annotate(Sum('amount'))
m = [{'a': x[0], 'b': x[1]} for x in m]

这两种方法当然都会强制评估整个查询集,并且不允许通过查询集的方法进行进一步的过滤/排序等。

另请注意,distinct()当您使用values()orvalues_list()时,调用 to 是多余的annotate()

于 2013-08-09T11:10:11.463 回答
9

您可以在 上使用F()表达式collected_by__username

F()对象表示模型字段或注释列的值。它可以引用模型字段值并使用它们执行数据库操作,而无需将它们从数据库中拉出到 Python 内存中……F()可用于在模型上创建动态字段……

如果您在annotate子句中执行此操作,我们可以将字段“重命名”为a. F()计算总数时不需要使用表达式。见下文:

from django.db.models import F
    
(Mainfee.objects.values('collected_by__username')
    .annotate(a=F('collected_by__username'), b=Sum('amount'))
    .values('a', 'b'))

对您的模型进行一些假设,这将产生如下内容:

<QuerySet [{'a': 'item1', 'b': 1234}, {'a': 'item2', 'b': 4321}]>
于 2019-04-25T07:50:29.250 回答
0

我不确定如何重命名第一个键,这里似乎有一个解决方案:How to rename items in values() in Django? 但在您的情况下它会返回错误,因为生成的 SQL 将是:

SELECT collected_by__username AS a WHERE ...

当然collected_by__username不存在。

注意:这里请求此功能https://code.djangoproject.com/ticket/16735

可以使用以下命令重命名第二个键:annotate(b=Sum('amount')

所以先试试这个:

m = (Mainfee.objects
     .extra(select={'a': 'collected_by.username'})  # check your DB for the exact table and field name
     .values('a')
     .distinct()
     .annotate(b=Sum('amount')))

我想它会抛出一个异常,但值得一试。否则现在不要尝试重命名第一个键,因为它会很笨拙。

希望能帮助到你。

于 2013-08-09T11:09:29.770 回答
-1

以防万一有人偶然发现此页面。

m = Mainfee.objects.extra(select = 'a':'collected_by.username'}).values('collected_by__username','a').distinct().annotate(b=Sum('amount'))
于 2016-06-29T15:39:17.087 回答