Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

213
Views
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 answers
Answer question

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 Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!