Получение объектов queryset, сгруппированных по диапазону значений аннотации

Мне нужно отфильтровать мои объекты таким образом, чтобы они были сгруппированы по диапазону (диапазон фиксирован, для данного случая, допустим, у нас есть эти 3 диапазона [0.0, 33.0] [33.01, 66.0] [66.01, 100.0]

вот моя модель

class Item(models.Model):
    name = models.CharField(
        help_text="Itemname",
        max_length=256
    )
    price = models.DecimalField(max_digits=6, decimal_places=2)

Я пытаюсь получить результат, который выглядит следующим образом

{
    "0.0-33.0": [`
        {
            "name": "x"
        }
    ],
    "33.01-66.0": [
        {
            "name": "y"
        },
        {
            "name": "Z"
        }
    ]
}

Я пробовал что-то вроде этого:

item_by_range = Item.objects.filter(price__lte=100.0).annotate(
    price_group=Case(
        When(price__range=[0.0, 33.0], then=Value('0-33')),
        When(price__range=[33.01, 66.0], then=Value('33-66')),
        When(price__range=[66.01, 100.0], then=Value('66-100')),
        default=Value('No group'),
        output_field=CharField(),
    )
).values('name', 'price_group').order_by('price_group')

но это работает только если я передаю в значениях только price_group, но так я теряю название товара

спасибо.

You only need to do some post-processing with groupby(…) [Python-doc] from the itertools module [Python-doc]:

from itertools import groupby
from operator import itemgetter

result = {
    k: [dict(name=v['name']) for v in vs]
    for k, vs in groupby(item_by_range, itemgetter('price_group'))
}

Это создаст словарь, который будет выглядеть следующим образом:

{
    "0.0-33.0": [
        {"name": x}
    ],
    "33.01-66.0": [
        {"name": y},
        {"name": z}
    }
}

Вы не можете создать объект, в котором один и тот же ключ (здесь "name") встречается несколько раз.

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