如何重命名带注释的查询的字段?

时间:2013-08-09 10:43:12

标签: django orm

我有以下查询

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 个答案:

答案 0 :(得分:7)

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

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]

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

另请注意,当您distinct()values()values_list()一起使用时,对annotate()的调用将是多余的。

答案 1 :(得分:1)

我不确定如何重命名第一个密钥,似乎这里有一个解决方案: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')))

我想它会吐出一个例外,但值得一试。否则,现在不要尝试重命名第一个键,因为它会非常hacky。

希望它有所帮助。

答案 2 :(得分:0)

万一有人在这个页面上绊倒。

m = Mainfee.objects.extra(select = 'a':'collected_by.username'}).values('collected_by__username','a').distinct().annotate(b=Sum('amount'))

答案 3 :(得分:0)

from django.db.models import F 

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