Reputation: 13
Hi help with values () method of queryset. When displaying related fields (Foreign key), the data is repeated, can this data be grouped?
class Product(models.Model):
category = models.ForeignKey(Category, related_name='product', on_delete=models.CASCADE)
title = models.CharField(max_length=250)
slug = models.SlugField(max_length=250, unique=True, db_index=True)
class ProductImage(models.Model):
product = models.ForeignKey(Product, related_name='product_image', on_delete=models.CASCADE)
image = models.ImageField(upload_to='img/models/')
is_main = models.BooleanField()
View code
data = Product.objects.all().values('pk', 'title', 'product_image')
Example here
This is how it is displayed
[
{'pk': 1, 'title': 'Product 1', 'product_image__image': 'img/models/mod_wpYzlnm.png'},
{'pk': 2, 'title': 'Product 2', 'product_image__image': 'img/models/mod2_wEr0D2q.png'},
{'pk': 2, 'title': 'Product 2', 'product_image__image': 'img/models/mod_pPQqmjB_we175uR.png'},
{'pk': 10, 'title': 'Product 3', 'product_image__image': 'img/models/mod_3mTxkb9_z4lKV3l.png'},
{'pk': 10, 'title': 'Product 3', 'product_image__image': 'img/models/heart.png'}
]
This is how it should be
[
{'pk': 1, 'title': 'Product 1, 'product_image':[
{'image':'img/models/mod_wpYzlnm.png'}
]},
{'pk': 2, 'title': 'Product 2', 'product_image': [
{'image':'img/models/mod2_wEr0D2q.png'},
{'image':'img/models/mod_pPQqmjB_we175uR.png'}
]},
{'pk': 10, 'title': 'Product 3', 'product_image': [
{'image':'img/models/mod_3mTxkb9_z4lKV3l.png'},
{'image':'img/models/heart.png'}
]},
]
Upvotes: 1
Views: 1017
Reputation: 476659
You should post-process the data with the groupby(…)
function [python-doc] of the itertools
module [python-doc]. For the query we should however first order on the pk
, or at least an item such that the queryset ProductImage
s is order such that all ProductImage
s of the same Product
are next of each other.
We can thus transform this with:
from itertools import groupby
from operator import itemgetter
data = Product.objects.values('pk', 'title', 'product_image').order_by('pk')
result = [
{'pk': pk, 'title': title,
'product_image': [ {'image': pi['product_image__image'] } for pi in pis ] }
for (pk, title), pis in groupby(data, itemgetter('pk', 'title'))
]
for the given sample data, this gives us:
[{'pk': 1,
'product_image': [{'image': 'img/models/mod_wpYzlnm.png'}],
'title': 'Product 1'},
{'pk': 2,
'product_image': [{'image': 'img/models/mod2_wEr0D2q.png'},
{'image': 'img/models/mod_pPQqmjB_we175uR.png'}],
'title': 'Product 2'},
{'pk': 10,
'product_image': [{'image': 'img/models/mod_3mTxkb9_z4lKV3l.png'},
{'image': 'img/models/heart.png'}],
'title': 'Product 3'}]
Upvotes: 1