Как вывести значения объекта с помощью "annotate()" и "for loop" в порядке возрастания?

У меня есть Category и Product модели ниже. *Я использую Django 3.2.16:

# "models.py"

from django.db import models

class Category(models.Model):
    name = models.CharField(max_length=20)

class Product(models.Model):
    category = models.ForeignKey(Category, on_delete=models.CASCADE)
    name = models.CharField(max_length=50)

Тогда, при выполнении test представления для печати id, name и product__count с annotate() и index, как показано ниже:

# "views.py"

from .models import Category
from django.http import HttpResponse
from django.db.models import Count

def test(request):
    qs = Category.objects.annotate(Count('product'))

    print(qs[0].id, qs[0].name, qs[0].product__count)
    print(qs[1].id, qs[1].name, qs[1].product__count)
    print(qs[2].id, qs[2].name, qs[2].product__count)
    print(qs[3].id, qs[3].name, qs[3].product__count)
    
    return HttpResponse("Test")

Они печатаются в порядке возрастания, как показано ниже:

1 Fruits 14
2 Vegetables 10
3 Meat 4
4 Fish 3

Но при выполнении test представления для печати id, name и product__count с annotate() и for loop, как показано ниже:

# "views.py"

# ...

def test(request):
    qs = Category.objects.annotate(Count('product'))

    for obj in qs:
        print(obj.id, obj.name, obj.product__count)
    
    return HttpResponse("Test")

Они печатаются в порядке убывания неправильно, как показано ниже:

4 Fish 3
2 Vegetables 10
3 Meat 4
1 Fruits 14
[25/Jan/202

Кроме того, при запуске test представления для печати id и name с all() и index как показано ниже:

# "views.py"

# ...

def test(request):
    qs = Category.objects.all()

    print(qs[0].id, qs[0].name)
    print(qs[1].id, qs[1].name)
    print(qs[2].id, qs[2].name)
    print(qs[3].id, qs[3].name)
    
    return HttpResponse("Test")

При выполнении test представления для печати id и name с all() и for loop как показано ниже:

# "views.py"

# ...

def test(request):
    qs = Category.objects.all()

    for obj in qs:
        print(obj.id, obj.name)
    
    return HttpResponse("Test")

Они печатаются в порядке возрастания, как показано ниже:

1 Fruits 14
2 Vegetables 10
3 Meat 4
4 Fish 3

Итак, как мне правильно вывести значения объекта с помощью annotate() и for loop в порядке возрастания?

Без порядка по, вы не можете делать никаких предположений о порядке. При подзаписи, когда набор запросов не упорядочен, Django упорядочит его по первичному ключу, чтобы предотвратить возврат одной и той же записи несколько раз. Вы можете упорядочить с помощью:

def test(request):
    qs = Category.objects.annotate(Count('product')).order_by('pk')

    for obj in qs:
        print(obj.id, obj.name, obj.product__count)

    return HttpResponse('Test')
Вернуться на верх