Queryset необходимо отсортировать в диктонарии

Могу ли я сортировать свой набор в пользовательском порядке. Под пользовательским порядком я имею в виду, что для каждых десяти полученных продуктов первые два должны быть тематическими (установленными на true), а остальные восемь должны быть нетематическими. Этот шаблон должен повторяться для каждого набора из десяти товаров и сохраняться в словаре. Словарь должен сохранять данные в формате 'id':'rank'. если is_featured такой же, то посмотрите rank. база данных должна быть задействована один раз.

    Product.objects.all().order_by('rank', '-created').values('is_featured', 'id', 'rank')


  <EavQuerySet [{'is_featured': True, 'id': 19, 'rank': -20241209}, {'is_featured': True, 'id': 18, 'rank': -20241209}, 
        {'is_featured': True, 'id': 17, 'rank': -20241209}, {'is_featured': True, 'id': 16, 'rank': -20241209}, {'is_featured': True, 'id': 15, 'rank': -20241209}, 
        {'is_featured': False, 'id': 14, 'rank': -20241209}, {'is_featured': False, 'id': 13, 'rank': -20241209}, {'is_featured': False, 'id': 12, 'rank': -20241209}, {'is_featured': False, 'id': 11, 'rank': -20241209}, 
        {'is_featured': False, 'id': 10, 'rank': -20241209}, {'is_featured': False, 'id': 9, 'rank': -20241209}, {'is_featured': False, 'id': 8, 'rank': -20241209}, {'is_featured': True, 'id': 7, 'rank': -20241206}, 
    {'is_featured': True, 'id': 6, 'rank': -20241206}, {'is_featured': False, 'id': 1, 'rank': -20241128}, {'is_featured': True, 'id': 4, 'rank': -20241128}, 
    {'is_featured': False, 'id': 5, 'rank': 0}, {'is_featured': False, 'id': 2, 'rank': 0}, {'is_featured': False, 'id': 3, 'rank': 0}]>

Просто обработайте элементы, разбив их на два итератора после получения данных, так:

from itertools import groupby, zip_longest
from operator import attrgetter

products = Product.objects.order_by('is_featured', 'rank', '-created')
items = {k: list(vs) for k, vs in groupby(products, attrgetter('is_featured'))}
featured = items.get(True, ())
featured = [featured[n : n + 2] for n in range(0, len(featured), 2)]
unfeatured = items.get(False, ())
unfeatured = [unfeatured[n : n + 8] for n in range(0, len(unfeatured), 8)]

result = {
    k: k.rank
    for fe, unfe in zip_longest(featured, unfeatured, fillvalue=())
    for k in (*fe, *unfe)
}

Это создаст словарь, который сопоставляет Product объекты со старым рангом, причем в порядке: сначала два featured, затем восемь unfeatured, затем два featured и т.д.

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