在 Odoo 开发中,fields_view_get 方法是一个强大的工具,使开发者能够在视图渲染之前对其进行定制,包括动态设置字段的 Domain。本文将探讨如何使用 fields_view_get 方法动态设置字段 Domain,提供一个详细的实现指南。

fields_view_get 方法概述

fields_view_get 是 Odoo 模型中的核心方法,负责在渲染视图时返回视图的结构和定义。开发者可以通过重写此方法,在视图加载前对其进行修改,如改变字段属性、添加过滤器或动态设置字段的 Domain。

应用场景

假设有一个场景,我们需要在一个处理费用报销审批流程的向导中,根据业务逻辑动态设置一个字段的 Domain,以过滤出与选定的费用报销记录相关的审批人选项。

实现方法

1. 定义模型和字段

首先定义向导模型及所需字段,例如添加 original_approver_id 和 new_approver_id 字段,均指向 hr.employee 模型。

from odoo import models, fields

class ExpenseTransferApproverWizard(models.TransientModel):
    _name = 'expense.transfer.approver.wizard'
    _description = 'Expense Transfer Approver Wizard'

    original_approver_id = fields.Many2one('hr.employee', string='Original Approver', required=True)
    new_approver_id = fields.Many2one('hr.employee', string='New Approver', required=True)

2. 覆盖 fields_view_get 方法

重写 fields_view_get 方法,以在视图加载时动态设置 original_approver_id 字段的 Domain。

from odoo import api, models
from lxml import etree
import json

class ExpenseTransferApproverWizard(models.TransientModel):
    # 模型定义省略...

    @api.model
    def fields_view_get(self, view_id=None, view_type='form', toolbar=False, submenu=False):
        res = super(ExpenseTransferApproverWizard, self).fields_view_get(view_id, view_type, toolbar, submenu)

        # 从上下文获取相关信息
        context_expense_id = self._context.get('active_id')
        if context_expense_id:
            unchecked_users_ids = self.env['order.check.line'].search(
                [('expense_id', '=', context_expense_id), ('is_checked', '=', False)]
            ).mapped('user_id.id')

            # 动态更新 original_approver_id 字段的 domain
            doc = etree.XML(res['arch'])
            for node in doc.xpath("//field[@name='original_approver_id']"):
                node.set('domain', json.dumps([('id', 'in', unchecked_users_ids)]))
            res['arch'] = etree.tostring(doc, encoding='unicode')

        return res

这段代码动态构造 original_approver_id 字段的 Domain,并使用 lxml 修改视图定义以应用新的 Domain。

3. 视图和操作

在 XML 中定义向导的视图,并提供用户启动向导的操作。original_approver_id 和 new_approver_id 字段的 Domain 将根据 fields_view_get 方法中的逻辑动态更新。

与常规 Domain 设置的区别

使用 fields_view_get 方法动态设置 Domain 的主要优势在于其灵活性和动态性。相比于静态 Domain 定义,它允许基于用户当前上下文或特定业务规则实时调整 Domain,为用户提供更为精确和相关的选项。这种方法特别适用于需要根据其他字段的值或用户的特定操作动态变化选项的场景。常规domain一般是应用于本模型的字段,类似

user_id = fields.Many2one('res.users', domain=[('is_active', '=', True)])

如果想跨模型来写比较复杂的domain, 就可以考虑用fields_view_get方法设置domain