Odoo search方法优化:将allocated_sale_order查询移出循环
优化Odoo销售订单
test方法:移除循环内数据库查询 在销售订单的onchange关联方法中,原test逻辑会在循环里逐个查询关联销售订单,导致多次数据库请求。下面是优化后的代码,将循环内的查询逻辑移到外部,提升执行效率:
def test(self): tomorrow = datetime.datetime.today() + datetime.timedelta(days=1) date_list = [(tomorrow + datetime.timedelta(days=x)).date() for x in range(30)] # 查询符合条件的技师排班明细 technician_line = self.env["allocated_technician_line"].search( [ ("service_type_id", "=", self.service_type_id.id), ("time_slot", "=", self.time_slot), ("technician_id.user_id", "in", self.area_id.technicians.ids), ("allocated_technician_id.date", "in", date_list), ] ) if not technician_line: self["assigned_asc"] = False return # 收集所有需要查询的维度,一次性获取关联销售订单 active_id = self.env.context.get('active_id') domain = [ ("preferred_service_schedule", "in", technician_line.mapped('allocated_technician_id.id')), ("service_type_id", "in", technician_line.mapped('service_type_id.id')), ("time_slot", "=", self.time_slot), ("state", "!=", "cancel"), ] if active_id: domain.append(("id", "!=", active_id)) sale_orders = self.env["sale.order"].search(domain) # 构建订单统计映射:按(排班ID,服务类型ID)分组计数 order_count_map = {} for order in sale_orders: key = (order.preferred_service_schedule.id, order.service_type_id.id) order_count_map[key] = order_count_map.get(key, 0) + 1 # 遍历技师明细,计算可用配额并收集符合条件的排班ID allocated_technician_schedule_ids = [] for line in technician_line: key = (line.allocated_technician_id.id, line.service_type_id.id) order_count = order_count_map.get(key, 0) available_allocation = line.allocation - order_count if available_allocation > 0: allocated_technician_schedule_ids.append(line.allocated_technician_id.id) # 处理assigned_asc字段 if allocated_technician_schedule_ids: allocated_recs = self.env["allocated_technician"].browse(allocated_technician_schedule_ids) user_ids = allocated_recs.mapped('user_id').ids if self.assigned_asc.id not in user_ids: self["assigned_asc"] = False else: self["assigned_asc"] = False
优化要点
- 合并数据库查询:把原循环内的N次
sale.order查询合并成1次批量查询,大幅减少数据库交互开销。 - 用映射统计订单数:通过一次遍历查询结果,构建以「排班ID+服务类型ID」为键的计数映射,后续循环直接取统计值,避免重复处理订单集合。
- 提前判空精简逻辑:查询到
technician_line为空时直接设置字段并返回,跳过后续无意义的步骤。 - 统一过滤条件:把当前订单ID的过滤逻辑直接整合到查询domain中,替代循环内的
filtered操作,减少内存处理成本。
内容的提问来源于stack exchange,提问作者Sidharth Panda
相关产品推荐
相关产品推荐

