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

如何在Django ORM中合并无关联的Stock与Reserved查询集

问题描述

我正在编写一个Django视图,当前返回如下JSON结构:

[
    {
        "field_id" : 1,
        "stock" : [
            {
                "size" : "M",
                "total" : 3
            }
        ],
        "reserved" : [
            {
                "size" : "M",
                "total" : 1
            }
        ]
    },
    {
        "field_id" : 2,
        "stock" : [
            {
                "size" : "M",
                "total" : 2
            },
            {
                "size" : "PP",
                "total" : 2
            }
        ],
        "reserved" : [
            {
                "size" : "PP",
                "total" : 1
            },
            {
                "size" : "M",
                "total" : 2
            }
        ]
    }
]

为得到该结果,我使用了Django ORM的values和annotation:

reserved = Reserved.objects.all().values("size").annotate(total=Count("size")).order_by("total")

stock = Stock.objects.filter(amount=0).values('size').annotate(total=Count('size')).order_by('total')

目前该实现没问题,但我希望将reserved查询集的数据整合到stock中,得到如下JSON结构:

[ 
    { 
        "field_id" : 1, 
        "stock" : [ 
            { 
                "size" : "M", 
                "total" : 3, 
                "reserved": 1 
            } 
        ], 
    }, 
    { 
        "field_id" : 2, 
        "stock" : [ 
            { 
                "size" : "M", 
                "total" : 2, 
                "reserved": 1 

            }, 
            { 
                "size" : "PP", 
                "total" : 2, 
                "reserved": 0 
            } 
        ], 
    } 
]

注:Stock与Reserved模型之间无关联关系。请问是否可行?


解决方案

完全可行,核心思路是先把reserved数据转成便于快速查找的字典结构,再遍历stock数据补充对应的预留字段,具体步骤如下:

  1. 转换reserved数据为字典
    将reserved查询集转为{size: total}的键值对格式,这样能以O(1)时间复杂度查找对应尺码的预留数量:

    reserved_dict = {item['size']: item['total'] for item in reserved}
    
  2. 整合数据到stock条目
    假设你的field_id来自Stock模型(若为其他分组逻辑,仅需调整分组依据即可),先按field_id分组查询stock数据,再遍历每个条目补充reserved字段:

    # 按field_id和size分组查询stock数据
    stock_by_field = Stock.objects.filter(amount=0).values('field_id', 'size').annotate(total=Count('size')).order_by('field_id', 'size')
    
    # 按field_id分组整理最终数据
    result = {}
    for item in stock_by_field:
        field_id = item['field_id']
        size = item['size']
        # 获取当前尺码的预留数量,无匹配则设为0
        reserved_total = reserved_dict.get(size, 0)
        # 构建包含reserved字段的stock条目
        stock_item = {
            'size': size,
            'total': item['total'],
            'reserved': reserved_total
        }
        # 按field_id分组存储
        if field_id not in result:
            result[field_id] = {
                'field_id': field_id,
                'stock': []
            }
        result[field_id]['stock'].append(stock_item)
    
    # 转成最终的列表格式
    final_data = list(result.values())
    
  3. 返回JSON响应
    在Django视图中直接返回处理后的final_data:

    from django.http import JsonResponse
    
    def your_view(request):
        # 执行上述数据处理逻辑
        return JsonResponse(final_data, safe=False)
    

补充说明

  • 该方案仅需两次数据库查询(stock和reserved各一次),后续均为内存操作,效率较高;
  • 若field_id不是来自Stock模型,只需调整分组的判断逻辑,核心的字典转换和字段补充逻辑保持不变。

内容的提问来源于stack exchange,提问作者Joey Fran

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 07:01:57