如何在Django中重命名values()中的项目?


101

我想像djangoproject.com上的这张票一样执行相同的操作,但是具有一些附加格式。从这个查询

>>> MyModel.objects.values('cryptic_value_name')
[{'cryptic_value_name': 1}, {'cryptic_value_name': 2}]

我想得到这样的东西:

>>> MyModel.objects.values(renamed_value='cryptic_value_name')
[{'renamed_value': 1}, {'renamed_value': 2}]

是否有另一种更内置的方法,还是我必须手动执行此操作?

Answers:


72

这有点hacky,但是您可以使用以下extra方法:

MyModel.objects.extra(
  select={
    'renamed_value': 'cryptic_value_name'
  }
).values(
  'renamed_value'
)

这基本上是SELECT cryptic_value_name AS renamed_value在SQL中完成的。

如果您始终想要重命名的版本,但是数据库具有神秘名称,则另一种选择是使用新名称来命名字段,但用于db_column引用数据库中的原始名称。


6
显然,在1.7。*中,您可以直接将别名作为命名参数编写values()。资料来源:code.djangoproject.com/ticket/16735
gregoltsov 2014年

19
-1,因为.values(supports__through_tables)这种破解不会(可能是想重命名ValuesQuerySetdict键的最明显的用例)
wim 2014年

1
有没有人找到通过表(.values(supports__through_tables))做到这一点的方法?
弗朗索瓦·康斯坦特

12
遗憾的是,该解决方案不支持in中的相关名称.values('foreignkeymodel__id', 'foreignkeymodel__name')
Risadinha 2014年

13
来自票证16735的Model.objects.annotate(my_alias = F('some__long__name__to__alias'))。values('my_alias')。–
eugene

188

从中django>=1.8可以使用注释和F对象

from django.db.models import F

MyModel.objects.annotate(renamed_value=F('cryptic_value_name')).values('renamed_value')

extra()Django文档中也将不推荐使用

这是一个旧的API,我们打算在将来的某个时候弃用。仅当无法使用其他queryset方法表达查询时才使用它。如果确实需要使用它,请在您的用例中使用QuerySet.extra关键字提交票证(请先检查现有票证的列表),以便我们增强QuerySet API的功能以允许删除extra()。我们不再改进或修复此方法的错误。


3
此答案仅适用于django>=1.8。启用查询表达式annotate以接受除聚合之外的表达式。参考:docs.djangoproject.com/en/1.9/releases/1.8/...
杨荣文

3
它可以工作,但是原始问题中提出的语法不是更好吗? MyModel.objects.values(renamed_value='cryptic_value_name')
2016年

11
MyModel.objects.values(renamed_value=models.F('cryptic_value_name'))作品
jarcoal

1
这个答案有效,但是是多余的。传递给您的关键字参数代表您values()传递annotate()(请参阅docs.djangoproject.com/en/2.2/ref/models/querysets/…)。MyModel.objects.values(renamed_value=F('cryptic_value_name'))IMO 的答案更加简单明了。
tobias.mcnulty

76

不使用任何其他管理器方法(已在上测试v3.0.4):

from django.db.models import F

MyModel.objects.values(renamed_value=F('cryptic_value_name'))

摘自Django docs

一个F()对象表示一个模型字段或注释的列的值。这样就可以引用模型字段值并使用它们执行数据库操作,而无需实际将它们从数据库中拉出到Python内存中。


5
要使用多个值,可以使用:MyModel.objects.values(renamed_value=F('cryptic_value_name'),renamed_value2=F('cryptic_value_name2'))
alpere

1
但是如果您要更改一个值并保留另一个值怎么办?使用annotate可以实现:inv.annotate(name=F('stock__name')).values('name', "price")但是在这种情况下,我看不到该方法应如何工作。inv.values(name=F("stock__name"), price=F("price"))->注释“价格”与模型上的字段冲突
Malte

1
@马耳他我认为没有必要使这个复杂化。试一试inv.values('price', name=F("stock__name"))。在python中,您只能将命名参数放在未命名参数之后。
Arpit Singh

0

我正在使用django 1.11.6

(并且key:value对与接受的答案相反)

这就是我如何使其适合我的项目

def json(university):
    address = UniversityAddress.objects.filter(university=university)
    address = address.extra(select={'city__state__country__name': 'country', 'city__state__name': 'state', 'city__name': 'city'})
    address = address.values('country', 'state', "city", 'street', "postal_code").get()
    return address

注意,添加同时的objects.filter()。extra()。values()与上面相同。


您可以看到.extra(select={cryptic_value:ranamed_value})与接受的答案相比具有相反的key:value
Sudip Bhattarai '18

-6

如果要重命名模式的几个字段,它比简单得多。

尝试

projects = Project.objects.filter()
projects = [{'id': p.id, 'name': '%s (ID:%s)' % (p.department, p.id)} for p in projects]

在这里,我name在表中没有字段,但是经过一点调整后我可以得到它。


10
–1评估查询集,这是一个大问题
wim 2016年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.