【问题标题】:How to rename items in values() in Django?如何在 Django 中重命名 values() 中的项目?
【发布时间】:2012-05-22 20:36:42
【问题描述】:

我想做与this ticket at 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}]

还有其他更内置的方法还是我必须手动执行此操作?

【问题讨论】:

    标签: django django-orm


    【解决方案1】:

    尝试作为 kwargs 传递:

    MyModel.objects.annotate(**{'A B C':F('profile_id')}).values('A B C')
    

    在我的例子中,结果集中每个值的键中都包含空格和其他特殊字符,所以这起到了作用。

    【讨论】:

      【解决方案2】:

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

      from django.db.models import F
      
      MyModel.objects.values(renamed_value=F('cryptic_value_name'))
      

      摘自Django docs

      F() 对象表示模型字段或注释的值 柱子。它可以引用模型字段值和 使用它们执行数据库操作而无需实际拉取 将它们从数据库中取出到 Python 内存中。

      【讨论】:

      • 您可以使用多个值:MyModel.objects.values(renamed_value=F('cryptic_value_name'),renamed_value2=F('cryptic_value_name2'))
      • 但是如果您想更改一个值并保留另一个值怎么办?使用注释是可能的:inv.annotate(name=F('stock__name')).values('name', "price") 但我看不出这种方法在这种情况下应该如何工作。 inv.values(name=F("stock__name"), price=F("price")) -> 注释“价格”与模型上的字段冲突
      • @Malte 我认为没有必要使这个复杂化。试试inv.values('price', name=F("stock__name"))。在 python 中,您只能将命名参数放在未命名参数之后。
      【解决方案3】:

      这有点hacky,但你可以使用extra 方法:

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

      这基本上是在 SQL 中做SELECT cryptic_value_name AS renamed_value

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

      【讨论】:

      • 显然在 1.7.* 中,您可以直接将别名作为命名参数写入values()。来源:code.djangoproject.com/ticket/16735
      • -1 因为.values(supports__through_tables) 而这个hack 没有(顺便说一句,这可能是想要重命名ValuesQuerySet dict 键的最明显用例)
      • 有没有人找到通过表(.values(supports__through_tables)) 做到这一点的方法?
      • 很遗憾,此解决方案不支持 .values('foreignkeymodel__id', 'foreignkeymodel__name') 中的相关名称。
      • Model.objects.annotate(my_alias=F('some__long__name__to__alias')).values('my_alias') 来自工单 16735。
      【解决方案4】:

      django>=1.8你可以使用annotate和F对象

      from django.db.models import F
      
      MyModel.objects.annotate(renamed_value=F('cryptic_value_name')).values('renamed_value')
      

      extra() 也将被弃用,从 django docs:

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

      【讨论】:

      • 此答案仅适用于django>=1.8。查询表达式使annotate 能够接受聚合以外的表达式。参考:docs.djangoproject.com/en/1.9/releases/1.8/…
      • 它可以工作,但不是原始问题中提出的语法好多了吗? MyModel.objects.values(renamed_value='cryptic_value_name')
      • MyModel.objects.values(renamed_value=models.F('cryptic_value_name')) 工作
      • 这个答案有效但多余。传递给values() 的关键字参数代表您通过annotate() 传递(请参阅docs.djangoproject.com/en/2.2/ref/models/querysets/…)。 MyModel.objects.values(renamed_value=F('cryptic_value_name')) 的答案更简单、更清晰,IMO。
      【解决方案5】:

      我正在使用 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}) 与接受的答案相比具有相反的键:值
      【解决方案6】:

      如果你想重命名模式的几个字段,这很简单。

      试试

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

      这里我的表中没有name 字段,但稍作调整后我可以得到它。

      【讨论】:

      • –1 它评估查询集,这是一个交易破坏者
      猜你喜欢
      • 1970-01-01
      • 2016-01-09
      • 2013-09-04
      • 1970-01-01
      • 1970-01-01
      • 2018-10-23
      • 1970-01-01
      • 2020-08-14
      • 2013-10-26
      相关资源
      最近更新 更多