I need to filter my objects in a way to get them grouped by range (range is fixed, for this case let's say we have these 3 ranges [0.0, 33.0] [33.01, 66.0] [66.01, 100.0]
here is my model
class Item(models.Model):
name = models.CharField(
help_text="Itemname",
max_length=256
)
price = models.DecimalField(max_digits=6, decimal_places=2)
I am trying to get a result that looks like this
{
"0.0-33.0": [`
{
"name": "x"
}
],
"33.01-66.0": [
{
"name": "y"
},
{
"name": "Z"
}
]
}
I tried something like this:
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')
but this only works if I pass only price_group in values but this way I lose the name of the item
thanks.
CodePudding user response:
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'))
}
This will make a dictionary that looks like:
{
"0.0-33.0": [
{"name": x}
],
"33.01-66.0": [
{"name": y},
{"name": z}
}
}
You can not make an object where the same key (here "name"
) occurs multiple times.