Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

212
Vistas
Resultados incorrectos con `anotar` + `valores` + `union` en Django

Vaya a editar para ver más ejemplos de código de la vida real, que no funcionan después de cambiar el orden de consulta

Aquí están mis modelos:

 class ModelA(models.Model): field_1a = models.CharField(max_length=32) field_2a = models.CharField(max_length=32) class ModelB(models.Model): field_1b = models.CharField(max_length=32) field_2b = models.CharField(max_length=32)

Ahora, crea 2 instancias cada una:

 ModelA.objects.create(field_1a="1a1", field_2a="1a2") ModelA.objects.create(field_1a="2a1", field_2a="2a2") ModelB.objects.create(field_1b="1b1", field_2b="1b2") ModelB.objects.create(field_1b="2b1", field_2b="2b2")

Si consulto solo un modelo con anotaciones, obtengo algo así:

 >>> ModelA.objects.all().annotate(field1=F("field_1a"), field2=F("field_2a")).values("field1", "field2") [{"field1": "1a1", "field2": "1a2"}, {"field1": "2a1", "field2": "2a2"}]

Este es el comportamiento correcto. El problema empieza, cuando quiero conseguir la unión de esos dos modelos:

 # model A first, with annotate query = ModelA.objects.all().annotate(field1=F("field_1a"), field2=F("field_2a")) # now union with model B, also annotated query = query.union(ModelB.objects.all().annotate(field1=F("field_1b"), field2=F("field_2b"))) # get only field1 and field2 query = query.values("field1", "field2") # the results are skewed: assert list(query) == [ {"field1": 1, "field2": "1a1"}, {"field1": 1, "field2": "1b1"}, {"field1": 2, "field2": "2a1"}, {"field1": 2, "field2": "2b1"}, ]

La aserción pasa correctamente, lo que significa que los resultados son incorrectos. Parece que los values() no coincidieron con el nombre de la variable, simplemente iteraron sobre el objeto como en una tupla. El valor de field1 es en realidad el ID del objeto y field2 es field1 .

Esto es bastante fácil de arreglar en modelos tan simples, pero mis modelos reales son bastante complejos y tienen una cantidad diferente de campos. ¿Cómo los uno correctamente?

EDITAR

A continuación, puede encontrar un ejemplo extendido que falla independientemente del orden de union() y values() : los modelos son un poco más grandes ahora, y parece que la cuenta de diferentes campos de alguna manera confunde a Django:

 # models class ModelA(models.Model): field_1a = models.CharField(max_length=32) field_1aa = models.CharField(max_length=32, null=True) field_1aaa = models.CharField(max_length=32, null=True) field_2a = models.CharField(max_length=32) extra_a = models.CharField(max_length=32) class ModelB(models.Model): extra = models.CharField(max_length=32) field_1b = models.CharField(max_length=32) field_2b = models.CharField(max_length=32)
 # test ModelA.objects.create(field_1a="1a1", field_2a="1a2", extra_a="1extra") ModelA.objects.create(field_1a="2a1", field_2a="2a2", extra_a="2extra") ModelB.objects.create(field_1b="1b1", field_2b="1b2", extra="3extra") ModelB.objects.create(field_1b="2b1", field_2b="2b2", extra="4extra") values = ("field1", "field2", "extra") query = ( ModelA.objects.all() .annotate( field1=F("field_1a"), field2=F("field_2a"), extra=F("extra_a") ) .values(*values) ) query = query.union( ModelB.objects.all() .annotate(field1=F("field_1b"), field2=F("field_2b")) .values(*values) )
 # outcome assert list(query) == [ {"field1": "1a1", "field2": "1a2", "extra": "1extra"}, {"field1": "2a1", "field2": "2a2", "extra": "2extra"}, {"field1": "3extra", "field2": "1b1", "extra": "1b2"}, {"field1": "4extra", "field2": "2b1", "extra": "2b2"}, ]
over 4 years ago · Santiago Trujillo
1 Respuestas
Responde la pregunta

0

Busqué en los documentos y debo admitir que no entendí completamente por qué su enfoque no funcionó (según tengo entendido, debería). Lo que creo es que aplicar la union a conjuntos de consultas con diferentes nombres de campo parece estar produciendo efectos extraños.

De todos modos, aplicar valores antes de hacer la unión parece producir resultados correctos:

 query = ModelA.objects.all().annotate(field1=F("field_1a"), field2=F("field_2a")).values('field1', 'field2') query = query.union(ModelB.objects.all().annotate(field1=F("field_1b"), field2=F("field_2b")).values('field1', 'field2'))

Lo que da como resultado este conjunto de consultas

 [ {'field1': '1a1', 'field2': '1a2'}, {'field1': '1b1', 'field2': '1b2'}, {'field1': '2a1', 'field2': '2a2'}, {'field1': '2b1', 'field2': '2b2'} ]
over 4 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda