Como faço para obter os objetos relacionados Em um extra (). Values ??() chamada no Django?

StackOverflow https://stackoverflow.com/questions/1138360

  •  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?

Foi útil?

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.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top