Odoo 自定义过滤功能

Odoo Custom filter function

我已经尝试了所有方法并到处搜索答案,但没有成功。

我想实现一个自定义函数来检索 Many2one selection 列表的过滤值。 通常你会为此使用域,但给出的域选项不足以实现我的目标。

我必须覆盖什么函数才能修改给定 Many2one 字段的 selection 列表?

谢谢, 拉斯

更新:

感谢您的回答。我使用 name_search 来分析生成的 WHERE 子句。 这是我想要实现的目标和我目前的发现:

programs = fields.Many2many(
        comodel_name='hr.program',
        relation='hr_process_onboarding_wizard_programs')
program_department = fields.Many2one(
        comodel_name='hr.department',
        domain="[('programs', 'in', programs)]")

字段程序表示为many2many_checkboxes小部件。 当我 select 2 个值时,以下域过滤器将传递给 name_search['programs', 'in', [1, 2]]

这将生成以下 SQL-Query(有趣部分的摘录):(SELECT "hr_department_id" FROM "hr_programs_departments" WHERE "hr_program_id" IN (1,2))

结果列表当然是程序 [1,2] 的 UNION,但我希望程序 [1,2] 是 INTERSECTION。

Afaik 没有域过滤器来获取交集。

更新 2:

在考虑了给定的过滤器运算符之后,我希望 = 完全按照我的意愿进行操作,但是运算符 = 生成与 in.[=18 相同的 WHERE 子句=]

我想我们在同一页上,我想建议 _search 方法,因为每次当你点击 many2one 字段时,这个 _search 方法与您在 py 中写入的域或 xml.

您可以覆盖它并发挥作用。

无论何时重写此类方法,您都需要注意一件事。 我建议你从你的领域传递上下文和 _search 方法中的一个条件(在所有代码之上)这样你的代码就不会影响到其他地方,因为使用了 _search 方法无处不在。

谢谢

这是我在 class HrDepartment 中使用 name_search 的快速破解解决方案。
我在相应视图的字段中添加了一个属性 context="{'intersect': True}",以便在其他上下文中实现故障保护。
domain 仍然存在并在 must_contain_programs 中使用。

@api.model
def name_search(self, name='', args=None, operator='ilike', limit=100):
    is_intersect_context = self._context.get('intersect')
    must_contain_programs = args[0][2]
    if(is_intersect_context and len(must_contain_programs) > 1):
        all_departments = self.env['hr.department'].search([])
        filtered_departments = []
        for department in all_departments:
            if all(program_id in department.programs.ids for program_id in must_contain_programs):
                filtered_departments.append(department)
        if len(filtered_departments) > 0:
            intersect_res = []
            for filtered_department in filtered_departments:
                intersect_res.append((filtered_department.id, filtered_department.name))
            intersect_res.sort(key=lambda tuple: tuple[0])
            if name != '':
                res = list(filter(lambda tuple: name.upper() in tuple[1].upper(), intersect_res))
            else:
                res = intersect_res
    else:
        res = super(HrDepartment, self).name_search(name, args, operator, limit)
    return res