Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

216
Visualizações
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 Respostas
Responde à pergunta

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 Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda