第三章 Reference字段的过滤
Reference字段是一种相对比较特殊的字段类型,它原生不支持Domain过滤,如果想要实现过滤则需要借助其他辅助工具。本文就将介绍如何使用context和name_search方法巧妙地间接地实现Reference的关联过滤效果。
Reference的问题
首先我们先来认识Reference的问题,我们知道Reference字段可以关联不同的数据模型,然后动态选择该数据模型下的数据记录,但是选择完数据模型以后,将显示该模型下的所有的数据记录。
如果尝试给Reference字段添加domain过滤,系统则会提示:
Domain on non-relational field "xxx" makes no sense (domain:[('parnter_id','=',False)])
也就是说,Reference字段不支持domain过滤。
解决方案
既然原生不支持,那么我们就需要通过其他方法间接实现此功能。首先我们知道Reference本质上是从Many2one字段继承而来,因此它原生支持name_get方法,既然我们希望在记录的选择中进行过滤,那么自然就可以使用name_search方法实现过滤。
这里的问题是,name_get方法针对于全局对象皆有效果,即你在某个对象上启用了name_search方法,那么对于系统中所有该模型的Many2one字段将同时生效,这可不是我们希望看到的。
这个时候,我们就可以通过field的context上下文对象传入一个特殊的值,在name_search方法中根据该值进行判断。
举例来说,我们在客户的某个项目中有个一Reference字段,关联了销售订单和线索两个对象
lead = fields.Reference(
selection=[('sale.order', '销售订单'), ('crm.lead', '商机/线索')])
然后我们在字段的视图文件中添加一个上下文:
<field name="lead" required="1" domain="[('partner_id','=',partner_id)]" />
然后我们在name_search方法中进行判断区分
@api.model
def name_search(self,name,args=None,operator='ilike',limit=100):
partner_id = self.env.context.get("partner_id",None)
if partner_id is not None:
args += [('partner_id','=',partner_id)]
return super(sale_order,self).name_search(name,args,operator,limit)
由于我们只在特定的页面添加了context,而且partner_id是我们自定义的字段,因此这种方法可以避免绝大多数原生页面中的Many2one字段的冗余逻辑问题。