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

如何在Django QuerySet中显示重复的Stock对象

问题描述

我有一个Stock模型,正尝试在数据库中查找重复项。当使用Stock.objects.filter(component__in=components)过滤时,期望显示所有重复对象,但该操作会自动排除重复项。比如我的components列表结构如下:

1
2
3
  1(子组件,可转换为component对象)
  2(子组件,可转换为component对象)
  3(子组件,可转换为component对象)
4
5
6
...

过滤后,第一个3下的1、2、3对象因ID相同被剔除,但我需要保留所有这些对象。

相关代码:

def get_custom_queryset(self):
        params = {}
        reference = False
        for param in iter(self.request.GET):
            if param.startswith('Search_'):
                search = param[7:]                
                if search == 'inventory':
                    try:
                        inventory = self.request.GET[param]
                        if inventory == 'on':
                            components, stock_codes = [], []
                            stock = Stock.objects.filter(is_inventory=True) # 不能用first(),因为self.table需要queryset而非列表
                            for s in stock:
                                stock_codes.append(s.component.code)
                            components_on_inventory = Component.objects.filter(code__in=stock_codes)
                            for coi in components_on_inventory:
                                if coi.has_subcomponents():
                                    qs_sc = []
                                    components.append(coi)
                                    for sc in coi.subcomponents():
                                        qs_sc.append(sc.subcomponent)
                                    components.append(qs_sc)
                                else:
                                    components.append(coi)
                            i = 0
                            while i < len(components):
                                if isinstance(components[i], list):
                                    sc_list = components[i]
                                    components = components[:i] + sc_list + components[i+1:]
                                i += 1
                            queryset = Stock.objects.filter(component__in=components)
                            if queryset.filter(is_inventory=False).exists(): # 有时Stock QuerySet会自动出现非库存组件,所以要删除这些项
                                queryset.filter(is_inventory=False).delete()
                            self.queryset = queryset
                            reference = True
                            break
                    except:
                        pass
解决方案

Django的__in查询会自动去重,因为数据库返回的是唯一行。要保留重复项,得换个方式处理:

  1. 收集包含重复ID的组件列表
    先把components转换成包含重复ID的列表,确保所有重复项都被保留:

    component_ids = [comp.id for comp in components]
    
  2. 循环查询每个ID对应的Stock对象,合并结果到列表
    放弃用__in一次性查询,改为循环每个ID查询,把结果添加到列表中(列表不会自动去重):

    stock_list = []
    for comp_id in component_ids:
        # 直接过滤is_inventory=True,省去后续删除步骤
        stocks = Stock.objects.filter(component_id=comp_id, is_inventory=True)
        stock_list.extend(stocks)
    
  3. 替换原代码中的查询逻辑
    把原代码里的queryset = Stock.objects.filter(component__in=components)及后续删除操作,替换为上面的列表生成逻辑:

    # 替换原代码中从queryset = ...到self.queryset = queryset的部分
    component_ids = [comp.id for comp in components]
    stock_list = []
    for comp_id in component_ids:
        stocks = Stock.objects.filter(component_id=comp_id, is_inventory=True)
        stock_list.extend(stocks)
    # 如果表格接受列表作为数据源,直接赋值
    self.queryset = stock_list
    
  4. 优化子组件收集逻辑
    原代码中展开子组件的循环可以简化,避免处理嵌套列表:

    # 替换原代码中收集components的循环
    components = []
    for coi in components_on_inventory:
        components.append(coi)
        if coi.has_subcomponents():
            # 直接把所有子组件添加到列表中
            components.extend([sc.subcomponent for sc in coi.subcomponents()])
    

注意:如果你的表格必须接收QuerySet作为数据源,那无法直接显示重复行(因为QuerySet是数据库层面的查询结果,天然去重),此时需要调整表格渲染逻辑,比如通过注解(annotate)统计每个组件的出现次数,在表格中显示次数而非重复行。

内容的提问来源于stack exchange,提问作者Diego David Brescia Rosa diego

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 20:05:05