You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何对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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.14 17:49:31