Django'da değerler () içindeki öğeler nasıl yeniden adlandırılır?


102

Djangoproject.com'daki bu biletle hemen hemen aynısını yapmak istiyorum , ancak bazı ek biçimlendirme ile. Bu sorgudan

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

Böyle bir şey almak istiyorum:

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

Başka, daha yerleşik bir yol var mı yoksa bunu elle yapmak zorunda mıyım?

Yanıtlar:


72

Biraz zor ama şu extrayöntemi kullanabilirsiniz :

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

Bu temelde SELECT cryptic_value_name AS renamed_valueSQL'de yapar.

Başka bir seçenek, her zaman yeniden adlandırılmış sürümü istiyorsanız, ancak db şifreli bir ada sahipse, alanınızı yeni adla db_columnadlandırmak, ancak veritabanındaki orijinal ada başvurmak için kullanmaktır .


6
Görünüşe göre 1.7. * 'Da sadece adlandırılmış bağımsız değişkenler olarak takma adlar yazabileceksiniz values(). Kaynak: code.djangoproject.com/ticket/16735
gregoltsov

19
-1 çünkü .values(supports__through_tables)ve bu hack değil (tesadüfen muhtemelen ValuesQuerySetdikt anahtarlarını yeniden adlandırmak için en bariz kullanım durumu )
wim

1
Bunu tablolar (.values ​​(supports__through_tables)) aracılığıyla yapmanın bir yolunu bulan var mı?
François Constant

12
Ne yazık ki, bu çözüm in gibi ilgili isimleri desteklemiyor .values('foreignkeymodel__id', 'foreignkeymodel__name').
Risadinha

13
Model.objects.annotate (my_alias = F ('some__long__name__to__alias')). Değerler ('my_alias') 16735.
eugene

189

Sizden django>=1.8açıklama ve F nesnesini kullanabilirsiniz

from django.db.models import F

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

Ayrıca django belgelerindeextra() kullanımdan kaldırılacak :

Bu, gelecekte bir noktada kullanımdan kaldırmayı hedeflediğimiz eski bir API'dir. Yalnızca sorgunuzu diğer sorgu kümesi yöntemlerini kullanarak ifade edemezseniz kullanın. Kullanmanız gerekiyorsa, lütfen QuerySet.extra anahtar sözcüğünü kullanarak kullanım durumunuzla birlikte bir bilet oluşturun (lütfen önce mevcut biletlerin listesini kontrol edin), böylece QuerySet API'sini fazladan () kaldırmaya izin verecek şekilde geliştirebiliriz. Artık bu yöntem için hataları iyileştirmiyoruz veya düzeltmiyoruz.


3
Bu cevap sadece işe yarar django>=1.8. annotateToplamalar dışındaki ifadeleri kabul etmek için Sorgu İfadeleri etkinleştirildi . Referans: docs.djangoproject.com/en/1.9/releases/1.8/…
Yeo

3
Çalışıyor, ancak orijinal soruda önerilen sözdizimi çok daha hoş değil mi? MyModel.objects.values(renamed_value='cryptic_value_name')
wim

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

1
Bu cevap işe yarıyor ama gereksiz. Aktarılan anahtar kelime argümanları sizin adınıza values()iletilir annotate()(bkz. Docs.djangoproject.com/en/2.2/ref/models/querysets/… ). Cevap MyModel.objects.values(renamed_value=F('cryptic_value_name'))daha basit ve daha net, IMO.
tobias.mcnulty

77

Başka bir yönetici yöntemi kullanmadan (üzerinde test edilmiştir v3.0.4):

from django.db.models import F

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

Django belgelerinden alıntı :

Bir F () amacı, bir Model alanı veya açıklamalı sütununun değerini temsil eder. Model alan değerlerine başvurmayı ve bunları kullanarak veritabanı işlemlerini gerçekten veritabanından Python belleğine çekmek zorunda kalmadan gerçekleştirmeyi mümkün kılar.


5
Birden fazla değer için şunları kullanabilirsiniz:MyModel.objects.values(renamed_value=F('cryptic_value_name'),renamed_value2=F('cryptic_value_name2'))
alpere

1
ama ya bir değeri değiştirip diğerini korumak isterseniz? Ek açıklama ile mümkün: inv.annotate(name=F('stock__name')).values('name', "price")ama bu durumda bu yöntemin nasıl çalışması gerektiğini anlamıyorum. inv.values(name=F("stock__name"), price=F("price"))-> 'Fiyat' ek açıklaması model üzerindeki bir alanla çakışıyor
Malte

1
@Malte Bunu karmaşıklaştırmaya gerek yok diye düşünüyorum. Sadece dene inv.values('price', name=F("stock__name")). Python'da yalnızca adlandırılmış bağımsız değişkenleri adlandırılmamış olanların arkasına koyabilirsiniz.
Arpit Singh

0

Django 1.11.6 ile çalışıyorum

(Ve anahtar: değer çifti, kabul edilen cevabın tersidir)

Projem için bu şekilde çalışmasını sağlıyorum

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

Eşzamanlı nesneler.filter (). Extra (). Değerler () eklemenin yukarıdakiyle aynı olduğunu unutmayın.


.extra(select={cryptic_value:ranamed_value})bunun karşıt anahtarı olduğunu görebilirsiniz : kabul edilen cevaba kıyasla değer
Sudip Bhattarai

-6

Modun birkaç alanını yeniden adlandırmak istiyorsanız, bu çok basit.

Deneyin

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

Burada nametabloda bir alanım yok , ancak biraz ince ayar yaptıktan sonra bunu alabilirim.


10
–1 bir anlaşma bozucu olan sorgu kümesini değerlendirir
wim
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.