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


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可能不总是指向当前表单的记录,尤其是在通过菜单项或关联字段打开表单时。

简小派 简小派

简小派是一款AI原生求职工具,通过简历优化、岗位匹配、项目生成、模拟面试与智能投递,全链路提升求职成功率,帮助普通人更快拿到更好的 offer。

简小派 103 查看详情 简小派

正确的做法是利用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的标签。
    • /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未来版本的兼容性。

以上就是Odoo 16:在表单视图中动态修改Tree视图属性的教程的详细内容,更多请关注其它相关文章!


# 前端  # node  # python  # 是在  # 上传推广剪辑视频网站  # 四月营销推广  # 淄博庆云网站建设  # 网站在国外推广  # 哈密百度知识营销推广招聘  # jquery seo有影响吗  # 广州seo排名机构  # 上犹网站关键词推广  # 陕西知名网站建设贵不贵  # 正在加载  # 序列化  # 浮点  # 是一个  # 加载  # 这是  # 重写  # 分页  # 表单  # 字符串解析  # xml处理  # xml解析  # 字节  # app  # 沈阳网站建设平台用途 


相关栏目: 【 Google疑问12 】 【 Facebook疑问10 】 【 优化推广96088 】 【 技术知识133117 】 【 IDC资讯59369 】 【 网络运营7196 】 【 IT资讯61894 】


相关推荐: 电脑从睡眠中被自动唤醒怎么办_Windows唤醒源事件查看与禁用【解决】  汽水音乐车机版官网5.0 汽水音乐车机版5.0版本下载入口  Linux如何优化系统启动流程_Linux启动项优化方案  猫眼电影app怎么查询电影院的营业时间_猫眼电影影院营业时间查询教程  解决Windows上Composer PATH变量冲突导致的命令无法识别问题  漫蛙漫画官方网站使用_漫蛙manwa网页版在线入口教程  家里的小飞虫总是不断,用什么方法可以彻底根除?  sf漫画官网登录入口直达_sf漫画官方正版网址  如何定制PrimeNG Sidebar的背景颜色  OPPO A3 WiFi频繁断开怎么办 OPPO A3网络优化技巧  被称为海蜈蚣的海洋动物是  菜鸟驿站的取件码忘了怎么办 手机快速查询指南  江苏大剧院会员卡购买步骤  行者app怎样导出日志  192.168.1.1路由器后台入口 192.168.1.1默认登录入口  奥克斯空调不制热啥毛病_奥克斯空调不制热原因分析及解决技巧  房产|直播|视频号怎么认证开通?|直播|需要什么资质?  小米倒班助手添加日历提醒  中大网校app做题记录清除方法  解决PHP MySQL数据库更新无响应:SQL查询语法错误解析  斯宾塞称XGP云游戏“蒸蒸日上”:正在构建一个游戏从未如此唾手可得的未来  《顺丰同城骑士》查看我的技能方法  实时数据流中高效查找最小值与最大值  《虎扑》取消评分记录方法  VS Code源代码管理(SCM)视图的进阶使用技巧  mysql中如何分析索引使用情况_mysql索引使用分析方法  C++如何使用CMake构建项目_C++ CMakeLists.txt编写入门教程  12306夜间购票失败? | 查看官方公布的暂停服务公告与应对方案  《花瓣》创建专辑方法  支付宝网页版在线入口 支付宝官网电脑登录入口  网站体验不好=浪费钱:如何提升-用户体验效果差  TikTok视频播放中断怎么办 TikTok播放异常修复方法  优化长HTML属性值:SonarQube警告与实用策略  悟空浏览器网页版链接 悟空浏览器网页版最新有效地址  search中maxlength属性用法解析  diskgenius分区工具如何设置Bios启动项  《地下城堡4:骑士与破碎编年史》墓穴挑战125攻略  《浙里办》电子发票开具方法  使用TinyButStrong生成HTML并结合Dompdf创建PDF教程  PHP页面重载时变量值不重置的实现方法  《知到》打卡课程方法  手机雨课堂网页版入口免登录 雨课堂网页版可点击直接进入  使用Python和NLTK从文本中高效提取名词的实用教程  HTML Canvas文本样式定制指南:解决外部字体加载与应用难题  电脑视频号|直播|如何分享屏幕  PHP utf8_encode 字符编码转换疑难解析与最佳实践  微信客户端如何找回密码_微信客户端忘记密码找回方法  虫虫漫画排行榜单入口_虫虫漫画编辑推荐入口  以下哪一个是适应长期护理制度发展而设立的新职业  太平年在哪个平台播出 

 2025-11-27

了解您产品搜索量及市场趋势,制定营销计划

同行竞争及网站分析保障您的广告效果

点击免费数据支持

提交您的需求,1小时内享受我们的专业解答。

运城市盐湖区信雨科技有限公司


运城市盐湖区信雨科技有限公司

运城市盐湖区信雨科技有限公司是一家深耕海外推广领域十年的专业服务商,作为谷歌推广与Facebook广告全球合作伙伴,聚焦外贸企业出海痛点,以数字化营销为核心,提供一站式海外营销解决方案。公司凭借十年行业沉淀与平台官方资源加持,打破传统外贸获客壁垒,助力企业高效开拓全球市场,成为中小企业出海的可靠合作伙伴。

 8156699

 13765294890

 8156699@qq.com

Notice

We and selected third parties use cookies or similar technologies for technical purposes and, with your consent, for other purposes as specified in the cookie policy.
You can consent to the use of such technologies by closing this notice, by interacting with any link or button outside of this notice or by continuing to browse otherwise.