讲师中心 微信公众号
AI工具推荐 视频效率加速

Odoo 16:在表单视图中动态修改Tree视图属性的教程

大伟吖_2493

大伟吖_2493

发布时间:2025-11-27 11:49:38

|

410人浏览过

|

来源于php中文网

原创

Odoo 16:在表单视图中动态修改Tree视图属性的教程

本教程详细介绍了如何在odoo 16的表单视图中,根据当前记录的数据动态修改内嵌tree视图的属性,例如设置分页限制。文章深入探讨了通过重写`get_view`方法并利用`self.env.context['params'].get('id')`准确获取当前记录id的关键技术,并提供了完整的代码示例和实现步骤,帮助开发者实现高度定制化的视图行为。

引言:动态视图定制的需求

Odoo提供了一套强大的视图系统,允许开发者通过XML定义界面的结构和行为。然而,在某些业务场景下,我们可能需要根据当前正在查看或编辑的记录的具体数据,动态地调整视图中某个组件的属性。一个常见的例子是在主表单中嵌入一个子Tree视图(也称为One2Many或Many2Many字段的列表视图),并希望根据主记录的某个字段值来改变这个子Tree视图的分页限制、可编辑性或列的显示。

本文将以在Odoo 16的stock.picking(调拨单)表单视图中,根据调拨单记录上定义的limit字段值,动态设置其关联的move_ids_without_package Tree视图(调拨行)的分页限制为例,详细讲解如何实现这一需求。

核心机制:重写 get_view 方法

Odoo在加载任何视图时,都会调用相应的模型上的get_view方法。这个方法是进行视图XML架构动态修改的理想入口点。通过重写此方法,我们可以在视图数据发送到前端渲染之前,对其XML结构进行解析、修改和重新序列化。

get_view方法接收以下主要参数:

  • view_id: 视图的数据库ID。
  • view_type: 视图的类型(如'form', 'tree', 'kanban'等)。
  • options: 包含额外上下文信息的字典。

准确获取当前记录ID

在get_view方法中,一个常见的挑战是准确获取当前正在加载的表单视图所对应的记录ID。开发者有时会尝试使用self.env.context.get('active_id'),但在get_view的上下文中,active_id可能不总是指向当前表单的记录,尤其是在通过菜单项或关联字段打开表单时。

python-code-analyz
python-code-analyz

专业Python代码分析与优化,支持语法检查、安全扫描、性能评估、复杂度分析及重构后优化代码生成。

下载

正确的做法是利用self.env.context['params'].get('id')。 params字典通常包含更精确的视图加载参数,其中id键会可靠地提供当前正在加载的表单视图所关联的记录的数据库ID。

实现动态Tree视图属性修改

下面我们将通过一个完整的代码示例,演示如何在stock.picking模型中实现根据记录的limit字段动态设置move_ids_without_package Tree视图的分页限制。

首先,我们需要在stock.picking模型中添加一个用于存储分页限制的字段,并重写get_view方法。

from odoo import models, fields, api
from lxml import etree
import logging

_logger = logging.getLogger(__name__)

class StockPicking(models.Model):
    _inherit = "stock.picking"

    limit = fields.Integer(string="Tree 分页限制", default=0, help="设置关联Tree视图的每页显示记录数。0表示不设置限制。")

    def tree_pagination_limit_apply(self):
        """
        一个示例方法,可以在用户界面中调用,以触发当前视图的重新加载,
        从而应用get_view中定义的动态修改。
        例如,可以在表单上添加一个按钮,点击后调用此方法。
        """
        return {
            'type': 'ir.actions.client',
            'tag': 'reload',
        }

    @api.model
    def get_view(self, view_id=None, view_type='form', **options):
        _logger.info(f"Custom get_view for StockPicking called for view_type: {view_type}")

        # 1. 调用父类方法获取原始视图架构
        # 这是非常重要的一步,确保Odoo的默认视图处理逻辑不被破坏
        result = super(StockPicking, self).get_view(view_id=view_id, view_type=view_type, **options)

        # 2. 仅在表单视图类型下进行修改,避免影响其他视图类型
        if view_type == 'form':
            # 3. 解析视图XML架构
            # 使用lxml库解析XML字符串,便于操作
            doc = etree.XML(result['arch'])

            # 4. 获取当前表单记录的ID
            # 关键:从self.env.context['params']中获取id,这是获取当前表单记录ID最可靠的方式
            active_id = self.env.context['params'].get('id') if 'params' in self.env.context else None

            if active_id:
                try:
                    # 5. 浏览当前记录以获取其数据
                    current_record = self.browse(active_id)
                    # 检查记录是否存在且limit字段值大于0才进行设置
                    if current_record and current_record.limit > 0:
                        # 6. 定位目标Tree视图并修改属性
                        # 使用XPath表达式精确查找名为'move_ids_without_package'的field下的'tree'标签
                        for tree_node in doc.xpath("//field[@name='move_ids_without_package']/tree"):
                            tree_node.set('limit', str(current_record.limit))
                            _logger.info(f"为记录ID {active_id} (Picking Name: {current_record.name}) 设置Tree视图限制为 {current_record.limit}")
                            break # 假设一个field下只有一个tree,找到后即可退出循环
                except Exception as e:
                    _logger.error(f"在设置Tree视图限制时发生错误 (记录ID: {active_id}): {e}")

            # 7. 将修改后的XML架构更新回结果中
            # lxml的tostring方法返回bytes,需要解码为unicode字符串
            result['arch'] = etree.tostring(doc, encoding='unicode').decode('utf-8')

        return result

代码解析与注意事项

  1. _inherit = "stock.picking": 继承stock.picking模型以添加新字段和重写方法。
  2. limit = fields.Integer(...): 定义一个整数字段limit,用于在每个调拨单记录上存储自定义的分页限制。default=0表示默认不设置限制。
  3. tree_pagination_limit_apply(self): 这是一个辅助方法,可以绑定到表单上的按钮。当用户点击该按钮时,它会触发客户端的reload动作,强制Odoo重新加载当前视图,从而使get_view中的修改生效。
  4. @api.model: get_view方法必须使用@api.model装饰器,因为它是一个类方法,不依赖于特定的记录集。
  5. result = super(StockPicking, self).get_view(...): 这是至关重要的一步。 始终先调用父类的get_view方法,以获取Odoo标准处理后的原始视图架构。在此基础上进行修改,可以避免破坏Odoo的默认视图逻辑。
  6. if view_type == 'form':: 限制修改仅在表单视图类型下进行。在其他视图类型(如列表视图、看板视图)下,Tree视图的结构和上下文可能不同,不应进行相同的修改。
  7. doc = etree.XML(result['arch']): 使用lxml库将视图的XML架构字符串解析为一个可操作的XML树对象。lxml是一个高性能的XML处理库,非常适合此类任务。
  8. active_id = self.env.context['params'].get('id'): 这是本教程的核心修复点。它确保我们获取到的是当前正在打开的表单记录的正确ID。
  9. current_record = self.browse(active_id): 通过获取到的active_id,浏览(browse)到对应的记录,以便访问其字段值(例如current_record.limit)。
  10. doc.xpath("//field[@name='move_ids_without_package']/tree"): 使用XPath表达式来定位目标Tree视图。
    • //field[@name='move_ids_without_package']:查找整个XML文档中所有名为move_ids_without_package的<field>标签。
    • /tree:在其子节点中查找<tree>标签。
    • lxml的xpath方法返回一个匹配元素的列表。
  11. tree_node.set('limit', str(current_record.limit)): 找到目标Tree节点后,使用set()方法修改其limit属性。注意,属性值必须是字符串。
  12. result['arch'] = etree.tostring(doc, encoding='unicode').decode('utf-8'): 将修改后的XML树重新序列化回字符串,并更新到result['arch']中。etree.tostring默认返回字节串,需要使用decode('utf-8')将其转换为Python字符串。
  13. 错误处理: 包含try-except块是良好的编程实践,可以捕获在XML解析、记录浏览或属性设置过程中可能发生的错误,防止整个系统崩溃,并记录详细日志以便调试。
  14. 性能考量: get_view方法在每次视图加载时都会执行。频繁的XML解析和序列化可能会带来一定的性能开销。因此,建议仅在确实需要动态修改视图时才使用此方法,并尽量优化XPath表达式和逻辑,减少不必要的处理。

总结

通过重写Odoo模型的get_view方法,并结合lxml库进行XML架构操作,我们可以实现高度灵活和动态的视图定制。关键在于理解get_view的执行时机,以及如何通过self.env.context['params'].get('id')可靠地获取当前表单记录的ID。掌握这些技术,开发者可以根据业务需求,创建更加智能和用户友好的Odoo界面。在实际应用中,务必注意代码的健壮性、性能影响以及与Odoo未来版本的兼容性。

热门AI工具

更多
Seko
Seko Hot

一款AI视频创作工具,主要用于商汤科技推出的创编一体的AI短视频创作Agent,适合需要提升相关任务效率的用户。

UpDream
UpDream Hot

一款AI视频创作工具,主要用于哔哩哔哩推出的自研AI视频创作工具,适合需要提升相关任务效率的用户。

UP简历
UP简历 Hot

一款AI办公效率工具,主要用于基于AI技术的免费在线简历制作工具,适合需要提升相关任务效率的用户。

火山引擎

火山引擎是一款面向企业的云计算与AI服务平台。

超级简历WonderCV

一款AI办公效率工具,主要用于免费求职简历模版下载制作,应届生职场人必备简历制作神器,适合需要提升相关任务效率的用户。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

SkildArt
SkildArt Hot

SkildArt是一款AI文本写作工具,一站式 AI 视觉创作平台。

相关专题

更多
pdf怎么转换成xml格式
pdf怎么转换成xml格式

将 pdf 转换为 xml 的方法:1. 使用在线转换器;2. 使用桌面软件(如 adobe acrobat、itext);3. 使用命令行工具(如 pdftoxml)。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

4124

2024.04.01

xml怎么变成word
xml怎么变成word

步骤:1. 导入 xml 文件;2. 选择 xml 结构;3. 映射 xml 元素到 word 元素;4. 生成 word 文档。提示:确保 xml 文件结构良好,并预览 word 文档以验证转换是否成功。想了解更多xml的相关内容,可以阅读本专题下面的文章。

5277

2024.08.01

xml是什么格式的文件
xml是什么格式的文件

xml是一种纯文本格式的文件。xml指的是可扩展标记语言,标准通用标记语言的子集,是一种用于标记电子文件使其具有结构性的标记语言。想了解更多相关的内容,可阅读本专题下面的相关文章。

2322

2024.11.28

js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

1598

2023.08.03

js截取字符串的方法
js截取字符串的方法

js截取字符串的方法有substring()方法、substr()方法、slice()方法、split()方法和slice()方法。本专题为大家提供字符串相关的文章、下载、课程内容,供大家免费下载体验。

2344

2023.09.04

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

5844

2023.10.24

字符串介绍
字符串介绍

字符串是一种数据类型,它可以是任何文本,包括字母、数字、符号等。字符串可以由不同的字符组成,例如空格、标点符号、数字等。在编程中,字符串通常用引号括起来,如单引号、双引号或反引号。想了解更多字符串的相关内容,可以阅读本专题下面的文章。

5029

2023.11.24

java读取文件转成字符串的方法
java读取文件转成字符串的方法

Java8引入了新的文件I/O API,使用java.nio.file.Files类读取文件内容更加方便。对于较旧版本的Java,可以使用java.io.FileReader和java.io.BufferedReader来读取文件。在这些方法中,你需要将文件路径替换为你的实际文件路径,并且可能需要处理可能的IOException异常。想了解更多java的相关内容,可以阅读本专题下面的文章。

6774

2024.03.22

LLVM自定义Pass怎么写
LLVM自定义Pass怎么写

本专题聚焦LLVM自定义Pass开发,整理Pass类结构、run()方法、PreservedAnalyses、CMake构建、插件注册、-load-pass-plugin加载和测试用例编写流程。

0

2026.09.30

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn