如何对Django EavQuerySet进行自定义分组排序并转换为指定格式字典
如何对Django EavQuerySet进行自定义分组排序并转换为指定格式字典
嘿,我来帮你搞定这个自定义排序的需求!咱们一步步来,保证只查询一次数据库,还能实现你要的每10个产品里前2个是featured、后8个是非featured的循环模式,最后转成指定格式的字典。
第一步:一次性获取所有数据(确保仅查询一次数据库)
首先,我们先把需要的产品数据一次性从数据库拉取出来,转成列表就能保证只触发一次数据库查询,完全符合你的要求:
# 按rank和created时间排序,获取所需字段,转成列表触发查询 products = list(Product.objects.all().order_by('rank', '-created').values('is_featured', 'id', 'rank'))
第二步:拆分featured和非featured产品(保留原有排序)
接下来,我们把featured和非featured的产品分开,用迭代器来处理,这样能高效地逐个取数:
from itertools import islice # 生成两个迭代器,分别对应featured和非featured产品,保留原排序 featured_iter = (p for p in products if p['is_featured']) non_featured_iter = (p for p in products if not p['is_featured'])
第三步:实现自定义分组排序逻辑
现在我们循环生成每一组:每次取2个featured产品,再取8个非featured产品,直到所有产品都被处理完毕:
sorted_products = [] while True: # 每次从featured迭代器取最多2个产品 chunk_featured = list(islice(featured_iter, 2)) # 每次从非featured迭代器取最多8个产品 chunk_non_featured = list(islice(non_featured_iter, 8)) # 如果两个分组都为空,说明所有产品处理完成,退出循环 if not chunk_featured and not chunk_non_featured: break # 把当前组的产品按顺序加入排序后的列表 sorted_products.extend(chunk_featured) sorted_products.extend(chunk_non_featured)
第四步:转换为指定格式的字典
最后,把排序后的产品列表转换成你需要的{'id': 'rank'}格式字典(如果不需要字符串格式,去掉str()即可):
# 生成id为键、rank为值的字典 result_dict = {str(p['id']): str(p['rank']) for p in sorted_products}
补充说明
- 这个方案完全满足你“只查询一次数据库”的要求,因为我们一开始就把所有数据拉取到内存中处理。
- 当featured或非featured产品数量不足一组的指定数量时(比如剩下1个featured产品),会自动取完剩余的产品,不会出现遗漏。
- 原QuerySet的排序逻辑(
is_featured相同时按rank排序)已经被保留,因为我们是基于原排序后的列表拆分迭代器的。
备注:内容来源于stack exchange,提问作者Nodirkhuja Khamitov
相关产品推荐
相关产品推荐

