¿Cómo consigo los objetos relacionados en un extra de valores (). (Call) en Django?

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

  •  16-09-2019
  •  | 
  •  

Pregunta

Gracias a este post que soy capaz de hacer contar fácilmente y el grupo de consultas en una vista de Django:

Django equivalente para el recuento y el grupo de

Lo que estoy haciendo en mi aplicación se muestra una lista de tipos de monedas y valores nominales disponibles en mi base de datos para un país, por lo que las monedas del Reino Unido podrían tener un valor nominal de "1 céntimo" o "6 peniques". El face_value es la 6, la currency_type es el "peniques", almacenada en una tabla relacionada.

Tengo el siguiente código en mi opinión, que me pone el 90% del camino:

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

El currency_type_id aparece como el número almacenado en el campo de clave externa (es decir, 4). Lo que quiero hacer es recuperar el objeto real que se hace referencia como parte de la consulta (el modelo de moneda, para que pueda obtener el campo Currency.name en mi plantilla).

¿Cuál es la mejor manera de hacer eso?

¿Fue útil?

Solución 2

select_related() me hizo bastante cerca, pero quería que añadir todos los campos que he seleccionado a la cláusula group_by.

Así que probé añadiendo values() después de la select_related(). No vayas. Luego he intentado varias permutaciones de cada uno en diferentes posiciones de la consulta. Cerca, pero no del todo.

terminé "wimping fuera" y simplemente utilizando SQL crudo, ya que yo ya sabía cómo escribir la 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 } )

Si hay una manera de expresar esa consulta exacta en el idioma queryset Django Sería curioso saber. Imagino que un SQL unirse con un recuento y la agrupación por dos columnas no es súper rara, así que me sorprendería si no había una manera limpia.

Otros consejos

No se puede hacer con values(). Pero no hay necesidad de usar que -. Que sólo puede conseguir los objetos Collectible reales, y cada uno tendrá un atributo currency_type que será el objeto vinculado relevante

Y como justinhamade sugiere, utilizando select_related() ayudará a reducir el número de consultas de bases de datos.

Juntando todo, se obtiene:

coin_values = Collectible.objects.filter(country=country.id, 
                    type=1).extra(
                    select={'count': 'count(1)'}, 
                    order_by=['-count']
                ).select_related()

Ha intentado select_related () http: // docs. djangoproject.com/en/dev/ref/models/querysets/#id4

Yo uso mucho parece que funciona bien, entonces se puede ir coin_values.currency.name.

Además no creo que lo que necesita hacer país = country.id en el filtro, solo país = país, pero no estoy seguro de qué diferencia que hace que no sea inferior a escribir.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top