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

rjv*_*rjv 3 django orm

我有以下查询

a = Mainfee.objects.values('collected_by__username').
                       distinct().annotate(Sum('amount'))
Run Code Online (Sandbox Code Playgroud)

结果看起来像这样

[{'collected_by__username': u'maindesk', 'amount__sum': 800}]
Run Code Online (Sandbox Code Playgroud)

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

我尝试了以下内容

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

收到了这个

DatabaseError: no such column: collected_by__username
Run Code Online (Sandbox Code Playgroud)

我也试过了

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

得到了

[{'collected_by__username': u'maindesk', 'amount__sum': 800}]
Run Code Online (Sandbox Code Playgroud)

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

小智 8

您可以在 上使用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'))
Run Code Online (Sandbox Code Playgroud)

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

<QuerySet [{'a': 'item1', 'b': 1234}, {'a': 'item2', 'b': 4321}]>
Run Code Online (Sandbox Code Playgroud)

  • 您能否添加一些详细信息,为什么这是该问题的答案? (5认同)

knb*_*nbk 7

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

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

[{'collected_by__username': u'maindesk', 'b': 800}]
Run Code Online (Sandbox Code Playgroud)

但是,没有快速简便的方法来重命名相关字段.你可以用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]
Run Code Online (Sandbox Code Playgroud)

或者这可能稍快一点:

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

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

另请注意,distinct()当您使用values()values_list()与之一起使用时,呼叫是多余的annotate().