Почему объединение 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

Вернуться на верх