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

別の組み込みの方法はありますか、または手動で行う必要がありますか?

回答:


72

それは少しハックですが、あなたはextraメソッドを使うことができます:

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

これは基本的に SELECT cryptic_value_name AS renamed_value SQLで行われます。

別のオプションとして、常に名前が変更されたバージョンが必要だが、dbに不可解な名前がある場合は、フィールドに新しい名前を付けますdb_columnが、dbの元の名前を参照するために使用します。


6
どうやら1.7。*では、エイリアス名をへの名前付き引数としてそのまま書き込むことができるようvalues()です。出典:code.djangoproject.com/ticket/16735
gregoltsov 2014

19
-1の理由.values(supports__through_tables)と、このハックはそうではありません(おそらく、ValuesQuerySetdictキーの名前を変更したい場合の最も明白な使用例です)
wim

1
テーブル(.values(supports__through_tables))を使用してこれを行う方法を誰かが見つけましたか?
フランソワ・コンスタント

12
残念ながら、このソリューションはのような関連する名前をサポートしていません.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 docsから非推奨になる予定です

これは、将来的に廃止予定の古いAPIです。他のquerysetメソッドを使用してクエリを表現できない場合にのみ使用してください。これを使用する必要がある場合は、QuerySet.extraキーワードを使用してチケットを提出してください(最初に既存のチケットのリストを確認してください)。QuerySetAPIを拡張して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 2017年

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
しかし、一方の値を変更し、もう一方の値を保持したい場合はどうでしょうか?アノテーションでそれは可能です:inv.annotate(name=F('stock__name')).values('name', "price")しかし、私はその場合にこの方法がどのように機能するべきかわかりません。inv.values(name=F("stock__name"), price=F("price"))->注釈「価格」がモデルのフィールドと競合しています
マルト

1
@マルテこれを複雑にする必要はないと思います。試してみてくださいinv.values('price', name=F("stock__name"))。Pythonでは、名前のない引数の後にのみ名前付きの引数を置くことができます。
Arpit Singh

0

私はdjango 1.11.6で働いています

(そして、キーと値のペアは受け入れられた答えのペアと反対です)

これは私のプロジェクトで機能させる方法です

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

同時オブジェクトを追加することに注意してください。filter()。extra()。values()は上記と同じです。


.extra(select={cryptic_value:ranamed_value})受け入れられた回答と比較してkey:valueが逆であることがわかります
Sudip Bhattarai

-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
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.