Почему объединение Django путает порядок столбцов?
Если у меня есть 2 модели:
class Hero(models.Model):
hero_name = models.CharField(max_length=50)
hero_age = models.PositiveSmallIntegerField()
hero_identity = models.TextField(max_length=50)
def __str__(self):
return self.hero_name
class Villain(models.Model):
villain_name = models.CharField(max_length=50)
villain_age = models.PositiveSmallIntegerField()
villain_identity = models.TextField(max_length=50)
def __str__(self):
return self.villain_name
и я создаю несколько тестовых экземпляров:
Hero(hero_name="Superman", hero_age=30, hero_identity="Clark Kent").save()
Hero(hero_name="Iron Man", hero_age=35, hero_identity="Tony Stark").save()
Hero(hero_name="Spider-Man", hero_age=18, hero_identity="Peter Parker").save()
Villain(villain_name="Green Goblin", villain_age=45, villain_identity="Norman Osborn").save()
Villain(villain_name="Red Skull", villain_age=38, villain_identity="Johann Schmidt").save()
Villain(villain_name="Vulture", villain_age=47, villain_identity="Adrian Toomes").save()
Перечисление их по отдельности работает нормально, но перечисление их с помощью союза как-то нарушает порядок:
>>> from django.db.models import F
>>> from myapp.models import Hero, Villain
>>> for hero in Hero.objects.all().annotate(name=F("hero_name"), age=F("hero_age"), identity=F("hero_identity")).values("name", "age", "identity"):
... print(hero)
{'name': 'Superman', 'age': 30, 'identity': 'Clark Kent'}
{'name': 'Iron Man', 'age': 35, 'identity': 'Tony Stark'}
{'name': 'Spider-Man', 'age': 18, 'identity': 'Peter Parker'}
>>> for villain in Villain.objects.all().annotate(name=F("villain_name"), age=F("villain_age"), identity=F("villain_identity")).values("name", "age", "identity"):
... print(villain)
{'name': 'Green Goblin', 'age': 45, 'identity': 'Norman Osborn'}
{'name': 'Red Skull', 'age': 38, 'identity': 'Johann Schmidt'}
{'name': 'Vulture', 'age': 47, 'identity': 'Adrian Toomes'}
>>> all = Hero.objects.all().annotate(name=F("hero_name"), age=F("hero_age"), identity=F("hero_identity")).union(Villain.objects.all().annotate(name=F("villain_name"), age=F("villain_age"), identity=F("villain_identity")))
>>> for person in all.values("name", "age", "identity"):
... print(person)
{'name': 1, 'age': 'Green Goblin', 'identity': 45}
{'name': 1, 'age': 'Superman', 'identity': 30}
{'name': 2, 'age': 'Iron Man', 'identity': 35}
{'name': 2, 'age': 'Red Skull', 'identity': 38}
{'name': 3, 'age': 'Spider-Man', 'identity': 18}
{'name': 3, 'age': 'Vulture', 'identity': 47}
Значения в столбце name
отображаются как значения столбца id
для каждой строки, значения имени находятся в столбце age
, значения age
в столбце identity
, а значения identity
вообще не отображаются.
Примечание: Чтобы перечислить их по отдельности, мне, очевидно, не нужно это annotate
- я могу просто использовать оригинальные имена столбцов - но с помощью аннотации я сохраняю данные как можно ближе к операции до объединения.
Примечание: Здесь используется Django версии 3.2.7