Como faço para obter os objetos relacionados Em um extra (). Values ??() chamada no Django?
-
16-09-2019 - |
Pergunta
Graças a este post eu sou capaz de facilmente fazer a contagem e agrupar por consultas em uma exibição de Django:
Django equivalente para contagem e agrupar por
O que estou fazendo em meu aplicativo está exibindo uma lista de tipos de moedas e valores de face disponíveis no meu banco de dados para um país, então as moedas do Reino Unido pode ter um valor de face de "1 centavo" ou "6 pence". O face_value
é o 6, o currency_type
é o "pence", armazenadas em uma tabela relacionada.
Eu tenho o seguinte código no meu ponto de vista que me recebe 90% do caminho até lá:
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 } )
O currency_type_id
surge como o número armazenado no campo de chave externo (ou seja, 4). O que eu quero fazer é recuperar o objeto real que referências como parte da consulta (o modelo de moeda, para que eu possa obter o campo Currency.name no meu modelo).
Qual é a melhor maneira de fazer isso?
Solução 2
select_related()
me ficou muito perto, mas ele me queria adicionar todos os campos que eu selecionado para a cláusula group_by
.
Então, eu tentei acrescentar values()
após a select_related()
. Não vá. Então eu tentei várias permutações de cada um em diferentes posições da consulta. Close, mas não completamente.
acabei "wimping out" e apenas usando SQL puro, desde que eu já sabia como escrever a consulta 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 há uma maneira de frase que consulta exata na língua queryset Django eu estaria curioso para saber. Imagino que um SQL juntar-se com uma contagem e agrupar por duas colunas não é super-raro, então eu ficaria surpreso se não houvesse uma maneira limpa.
Outras dicas
Você não pode fazê-lo com values()
. Mas não há necessidade de usar isso -. Você pode simplesmente pegar os objetos Collectible
reais, e cada um terá um atributo currency_type
que será o objeto vinculado relevantes
E como justinhamade sugere, usando select_related()
vai ajudar a reduzir o número de consultas de banco de dados.
Colocá-lo juntos, você obtém:
coin_values = Collectible.objects.filter(country=country.id,
type=1).extra(
select={'count': 'count(1)'},
order_by=['-count']
).select_related()
Você já tentou select_related () http: // docs. djangoproject.com/en/dev/ref/models/querysets/#id4
Eu uso muito isso parece funcionar bem, então você pode ir coin_values.currency.name.
Além disso eu não acho que você precisa fazer country = country.id em seu filtro, apenas country = país, mas não estou certo de que diferença isso faz que não seja menos digitação.