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

Posted

技术标签:

【中文标题】如何重命名带注释的查询的字段?【英文标题】:How to rename fields of an annotated query? 【发布时间】:2013-08-11 06:43:54 【问题描述】:

我有以下问题

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:我也想重命名第二个字段

【问题讨论】:

对于values:***.com/questions/10598940/… 【参考方案1】:

您可以在collected_by__username 上使用F() expression:

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]>

【讨论】:

您能否补充一些细节,为什么这是问题的答案? 在您的答案中添加了对 F() 表达式的一些解释。此外,虽然您在正确的路线上,但您没有将总数转换为 b,所以我已经更正了。【参考方案2】:

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

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

【讨论】:

F 似乎是更好的方法:***.com/questions/10598940/…【参考方案3】:

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

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]

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

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

【讨论】:

【参考方案4】:

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

我想它会抛出一个异常,但值得一试。否则暂时不要尝试重命名第一个键,因为这样会很麻烦。

希望对你有帮助。

【讨论】:

如果没有JOIN 语句,就无法在 SQL 级别上执行此操作,这需要侵入 Django ORM 或一些原始 SQL 语句。即使使用Mainfee.objects.raw() 也是不可能的,因为这需要一个 id,而如果不按它进行分组,您就无法选择它。 是的,这就是为什么我建议他放弃这个想法。

以上是关于如何重命名带注释的查询的字段?的主要内容,如果未能解决你的问题,请参考以下文章

MS Access VBA循环查询和重命名文件

是否可以重命名 PyMongo 中 Mongo 查询输出中的字段?

oracle 查询数据重命名为汉字对效率有影响吗?

Oracle查询语句中重命名的列在WHERE中无效?

使用聚合重命名 MongoDB 中的字段

Db4o - 如何一步重命名字段?