Come posso ottenere gli oggetti relativi a un extra di valori (). () Chiamata a Django?
-
16-09-2019 - |
Domanda
Grazie a questo post Sono in grado di fare facilmente contare e di gruppo per le query in una vista Django:
Django equivalente per il conteggio e il gruppo da
Quello che sto facendo nella mia app è la visualizzazione di un elenco di tipi di monete e valori nominali disponibili nel mio database per un paese, in modo da monete del Regno Unito potrebbe avere un valore nominale di "1 centesimo" o "6 pence". Il face_value
è il 6, il currency_type
è il "pence", memorizzata in una tabella correlata.
Ho il seguente codice a mio avviso che mi ottiene il 90% del tragitto:
def coins_by_country(request, country_name):
country = Country.objects.get(name=country_name)
coin_values = Collectible.objects.filter(country=country.id, type=1).extra(select={'count': 'count(1)'},
order_by=['-count']).values('count', 'face_value', 'currency_type')
coin_values.query.group_by = ['currency_type_id', 'face_value']
return render_to_response('icollectit/coins_by_country.html', {'coin_values': coin_values, 'country': country } )
Il currency_type_id
si presenta come il numero memorizzato nel campo chiave esterna (cioè 4). Quello che voglio fare è recuperare l'oggetto reale a cui fa riferimento come parte della query (il modello di valuta, in modo da poter ottenere il campo Currency.name nel mio modello).
Qual è il modo migliore per farlo?
Soluzione 2
select_related()
mi ha abbastanza vicino, ma voleva che io aggiungo ogni campo che ho scelto per la clausola group_by
.
Così ho provato aggiungendo values()
dopo la select_related()
. No Go. Poi ho provato varie permutazioni di ciascuno in diverse posizioni della query. Vicino, ma non del tutto.
Ho finito "wimping out" e solo usando SQL prime, dal momento che già sapevo come scrivere query SQL.
def coins_by_country(request, country_name):
country = get_object_or_404(Country, name=country_name)
cursor = connection.cursor()
cursor.execute('SELECT count(*), face_value, collection_currency.name FROM collection_collectible, collection_currency WHERE collection_collectible.currency_type_id = collection_currency.id AND country_id=%s AND type=1 group by face_value, collection_currency.name', [country.id] )
coin_values = cursor.fetchall()
return render_to_response('icollectit/coins_by_country.html', {'coin_values': coin_values, 'country': country } )
Se c'è un modo per frase quella query esatto nella lingua queryset Django sarei curioso di sapere. Immagino che un join SQL con un conteggio e raggruppamento da due colonne non è super-rara, quindi sarei sorpreso se non ci fosse un modo pulito.
Altri suggerimenti
Non si può farlo con values()
. Ma non c'è bisogno di utilizzare tale -. Si può solo ottenere gli oggetti Collectible
effettivi, e ognuno avrà un attributo currency_type
che sarà l'oggetto collegato relativo
E come justinhamade suggerisce, utilizzando select_related()
contribuirà a ridurre il numero di query di database.
Mettere insieme, si ottiene:
coin_values = Collectible.objects.filter(country=country.id,
type=1).extra(
select={'count': 'count(1)'},
order_by=['-count']
).select_related()
Hai provato select_related () http: // docs. djangoproject.com/en/dev/ref/models/querysets/#id4
Io lo uso molto sembra funzionare bene allora si può andare coin_values.currency.name.
Anche io non penso che devi fare country = country.id nel filtro, basta country = paese, ma non sono sicuro che differenza che rende diverso da meno di battitura.