恒美微站 Logo 恒美微站
  • 首页
  • 关于我们
  • 建站服务
  • 主题模板
  • 案例展示
  • 资讯中心
  • 联系我们

Odoo视图层实战:动作、视图与菜单的协作机制

  • 首页
  • 资讯中心
  • /
  • Odoo视图层实战:动作、视图与菜单的协作机制

相关资讯

串联锂电池主动均衡:MP2642GR-Z与PIC18F4455实现 2026/10/16 1:22:09
Apollo-11制导计算机源码深度拆解:从绳存储器到实时容错设计 2026/10/16 1:22:09
AS5245磁角度传感器实战:从选型、校准到电机FOC应用 2026/10/16 1:22:09

最新资讯

MooTool Next Compose 并行移植:JSON 结果弹层复制状态栏反馈(DIFF-295)实现解析
虚拟陀螺仪(软陀螺)适用角速度范围技术分析
Vivado HLS设计流程详解:从C代码到RTL硬件的映射与优化
LAMMPS 逐原子力矩施加指南:深入解析 fix addtorque/atom 命令的语法、变量机制与 GRANULAR 包实现
MCreator 方块原版工具挖掘等级(Vanilla Tool Tier)完整指南:配置、生成原理与自定义扩展
Vue 3 自定义视频播放器控制器:从0到1完整实现指南

今日推荐

Java八种基本类型深度解析:从内存布局到实战选型
基础:常用快捷键——IDEA、VS Code、PyCharm 与 Linux 终端效率速查
解决ultraedit下verilog .v文件中文注释乱码:把编码配置改到TaoToken辅助排查

本周热门

UE动画修改实战:从资产编辑到重定向与蒙太奇驱动
统计随机数生成器攻击下的KLJN安全密钥交换协议Matlab仿真
政务API安全治理:资产测绘、低代码编排与行标对标实践

本月精选

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证
2026 大模型集体涨价:用 Python 做企业 Token 成本测算与选型避坑(附配置)

Odoo视图层实战:动作、视图与菜单的协作机制

发布时间:2026/10/16 1:22:09
Odoo视图层实战:动作、视图与菜单的协作机制 1. 视图层不只是XML动作、视图与菜单的协作机制1.1 先想清楚模型、视图、动作三者分别干什么很多朋友做到“视图层”这一讲容易把注意力全部放在XML标签上总觉得form、tree写对了界面就能出来。其实在Odoo里视图层有一个非常明确的三角关系模型负责数据规则视图负责展示形式动作负责把“哪个模型、用哪些视图、加什么过滤条件”打包成一个可供菜单调用的入口。我在带新人做模块开发时最常用的一个类比是模型是仓库里的货架视图是货架上的不同标签牌动作则是那个“引导员”。用户点开菜单先找到引导员动作引导员按你写好的清单把对应的标签牌视图挂出来。菜单本身不直接和模型打交道它只负责指向动作。所以你在自定义模块里写代码时哪怕只加一个很简单的分类字段也会牵动三处改动模型里加字段表单视图里加控件搜索视图里加过滤项。如果漏了任何一处功能虽然能用但用户会觉得这个界面“半成品”。反过来如果视图太多而动作没有按顺序组织用户又会觉得入口混乱。1.2 动作是“入口清单”view_mode 决定用户可以切换几种形态有经验以后你会发现一个模型的视图可以有很多套列表视图、表单视图、看板视图、搜索视图甚至还有日历和透视视图。但用户一次打开菜单默认看到什么能不能切换全由动作的view_mode决定。record idaction_training_course modelir.actions.act_window field namename课程管理/field field nameres_modeltraining.course/field field nameview_modelist,form,kanban/field field namedomain[(state, !, cancel)]/field field namecontext{search_default_group_state: 1}/field /record上面这段里view_mode写的是list,form,kanban表示用户可以在列表、表单、看板三种形态之间切换。这里有一个常见误区view_mode并不是“视图定义顺序”而是“入口顺序”。Odoo 会按这里的顺序从ir.ui.view里找到适合当前模型、且满足当前模式的视图记录。另外要注意不同版本对“列表视图”的称呼不一样。Odoo 17 之后官方方案里更倾向用list但很多老教程和旧版本代码里仍然写tree。如果你的项目是从旧版本升级过来的或者参考了不同时期的资料切记先确认当前版本的写法不要照抄。2. 视图类型那么多核心配置先抓这三个2.1 列表视图和表单视图是绝大多数业务的底盘列表视图是最容易上手的甚至可以只在动作里写view_modetree系统会自动生成一个默认列表。但生产环境不可能这么随意因为你总要控制显示哪些列、哪些字段只读、哪些字段可以点击跳转。record idview_training_course_tree modelir.ui.view field namenametraining.course.tree/field field namemodeltraining.course/field field namearch typexml list string课程列表 editablebottom field namename/ field namecategory/ field namestate widgetbadge/ field nameprice sum合计/ field namestart_date optionalshow/ /list /field /record这里我故意用了list而不是tree因为在较新的Odoo里新代码更推荐list。editablebottom表示允许在当前列表底部直接录入新记录这对内部管理类页面很实用。sum合计会在列表底部显示一个合计行适合金额、课时这类数值字段。表单视图的配置则要更细一些因为用户的日常操作大多集中在表单页。我的建议是要把“必填”“只读”“按状态显隐”这些规则放在模型层或视图层统一管理不要在界面层面靠前端校验硬撑。比如form string课程信息 header button nameaction_start string开始开班 typeobject classbtn-primary confirm确认开始该课程/ field namestate widgetstatusbar/ /header sheet group group field namename required1/ field namecategory/ /group group field nameteacher_id/ field namestart_date/ field nameduration/ field nameprice/ /group /group notebook page string说明 field namedescription/ /page /notebook /sheet /form这里有个很实用的经验表单视图里如果放了state字段并且用了statusbar控件用户就能看到当前状态流转的进度条。配合头部的按钮可以让“草稿-开班中-已结课”这种状态流变得非常直观。这个设计在自定义业务模块里出现频率极高几乎可以当作标准范式。2.2 看板视图状态型业务的“清单化”展示利器看板视图在不少新手眼里显得很神秘因为它用到了QWeb模板看起来像前端代码。其实看板的核心逻辑很简洁按某个字段分组把每条记录渲染成一张卡片。record idview_training_course_kanban modelir.ui.view field namenametraining.course.kanban/field field namemodeltraining.course/field field namearch typexml kanban classo_kanban_mobile field namename/ field namestate/ field namecategory/ field namecolor/ templates t t-namekanban-box div classoe_kanban_global_click div classo_kanban_card_header div classo_kanban_card_header_title field namename/ /div /div div classoe_kanban_details field namecategory/ field nameprice/ field namestate/ /div /div /t /templates /kanban /field /record要让看板真正好用关键往往不在卡片样式而在给模型补一个color整型字段。这个字段不是给人看的而是给看板卡片底色用的。你可以像下面这样加color fields.Integer(颜色索引)然后在看板模板里引用field namecolor/。Odoo 会根据数值对应到预置色板。如果你想让某条记录特别显眼比如即将开课的课程可以用widgetpriority或者自己写个小计算字段去更新颜色索引这样用户的视觉焦点就被引导过去了。看板的另一个隐藏功能是“分组拖拽”。默认情况下看板会按第一个分组字段展示比如state。用户可以直接把卡片从“草稿”拖到“开班中”如果模型里对应字段允许这条记录的状态就更新了。这个体验很好但要注意权限控制好不能让人随手把已结课的记录拖回草稿。2.3 搜索视图决定用户每天怎么找数据很多模块开发到后面真正被用户夸“好用”的往往不是界面多好看而是搜索是否顺手。搜索视图的配置并不复杂但粒度可以做得非常细。record idview_training_course_search modelir.ui.view field namenametraining.course.search/field field namemodeltraining.course/field field namearch typexml search field namename/ field namecategory/ field nameteacher_id/ filter namestate_ongoing string开班中 domain[(state, , ongoing)]/ filter namestate_done string已结课 domain[(state, , done)]/ separator/ filter namegroup_state string按状态分组 context{group_by: state}/ filter namegroup_category string按分类分组 context{group_by: category}/ /search /field /record这个搜索视图包含了三个最常用的元素普通字段搜索、过滤条件、分组条件。普通字段搜索会在搜索栏显示下拉框用户输入关键字后按对应字段匹配过滤条件则以按钮形式出现在搜索框下方一键切换数据的筛选范围分组条件则控制列表和看板的展示分组方式。我特别想提醒一个细节分组条件在很多业务场景里比过滤条件更重要。比如课程管理里“按分类分组”能让你一眼看到不同分类下有多少课程“按状态分组”则能让用户直接看到流程堵在哪个环节。如果你在建模块初期就规划好这些分组后面做报表统计时会省很多事。3. 实操分解从字段设计到一个可点击的菜单入口3.1 模块目录与数据文件的加载顺序到了视图层这一讲模块的文件结构也基本成型了。我这里以一个培训机构的课程管理模块为例展示最常规的目录training_center/ ├── __init__.py ├── __manifest__.py ├── models/ │ ├── __init__.py │ └── training_course.py ├── security/ │ └── ir.model.access.csv ├── views/ │ ├── training_course_views.xml │ └── menu_views.xml └── data/ └── demo_data.xml在__manifest__.py里顺序是敏感点。data列表里必须先加载安全文件再加载视图最后加载菜单。因为菜单引用了动作动作引用了视图视图又引用了模型权限。如果顺序颠倒系统在安装时就会提示找不到对应的XML ID。{ name: 培训中心, version: 1.0, depends: [base], data: [ security/ir.model.access.csv, views/training_course_views.xml, views/menu_views.xml, ], application: True, }这里有经验的人会再做一件事给模块名和XML ID设置清晰的前缀。比如这个模块叫training_center那所有视图的ID都以view_training_course_开头动作以action_training_course_开头。后期模块一旦多起来这个习惯能帮你少踩一半的“ID重复导致视图串线”的坑。3.2 一个完整可用的动作与菜单配置这一讲标题里强调“设置视图层”所以我把最常见的动作配置再展开讲一下。许多教程会把动作和菜单写在同一个XML文件里这是完全可行的也方便维护。record idaction_training_course modelir.actions.act_window field namename课程管理/field field nameres_modeltraining.course/field field nameview_modelist,kanban,form/field field namedomain[(state, !, cancel)]/field field namecontext{search_default_group_state: 1}/field /record record idview_training_course_form modelir.ui.view field namenametraining.course.form/field field namemodeltraining.course/field field namearch typexml form string课程信息 sheet group field namename/ field namecategory/ field nameprice/ field namestart_date/ /group /sheet /form /field /record menuitem idmenu_training_root name培训中心 sequence10/ menuitem idmenu_training_course name课程管理 parentmenu_training_root actionaction_training_course sequence20/这段代码里动作的context写了一句{search_default_group_state: 1}。这句话很多人不理解它并不是强制分组而是“默认帮用户打开按状态分组”的开关。如果对应的搜索视图里定义了一个名为group_state的分组过滤条件那用户一进页面就会看到数据已经按状态分组好了。这是一个非常实用的小技巧尤其在列表视图和看板视图里效果明显。菜单结构我建议分成两层根菜单 业务菜单。根菜单的sequence控制它在应用切换器里的排序业务菜单的sequence则控制在根菜单下拉列表里的顺序。如果以后还有报名管理、讲师管理等模块只要挂在同一个根菜单下整个业务域就非常整齐。3.3 在视图里放按钮动作串起关联窗口视图层不只是展示字段它还要承担操作入口的职责。最常见的是在表单页放一个按钮一键跳转到关联模型。我在这个课程模块里通常会加一个“查看报名学员”的智能按钮。模型里写一个返回动作的方法def action_open_students(self): return { name: 报名学员, type: ir.actions.act_window, res_model: training.student, view_mode: list,form, domain: [(course_id, , self.id)], context: {default_course_id: self.id}, }然后在表单视图的sheet外侧或顶部加按钮button nameaction_open_students typeobject string查看报名学员 classoe_stat_button iconfa-users/这个配置的核心思路是按钮的name对应模型方法typeobject表示调用Python方法context里预先设置默认值让用户从课程页面顺手创建一个关联学员时系统能自动填好课程字段。我在做这类跳转时会特别注意domain的写法。如果不在动作里限制domain那点击按钮后用户看到的是所有学员而不是当前课程的学员只差一个条件体验却天差地别。新手最容易漏的就是这一步。4. 权限与数据规则视图层背后的两道隐性门槛4.1 ir.model.access.csv 的字段顺序与权限粒度很多教程会把权限文件一笔带过但实际开发中权限文件写错导致的“能看见菜单但打开报错”是最常见的故障之一。这个CSV文件有五列必填项id、name、model_id:id、group_id:id、然后才是四个权限位。id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink access_training_course_user,training.course.user,model_training_course,base.group_user,1,1,1,0 access_training_course_manager,training.course.manager,model_training_course,base.group_system,1,1,1,1注意model_id:id的写法。模型名是training.course在权限文件里对应的外部ID是model_training_course把点号换成下划线。如果模型名里带有复杂前缀这个规则同样适用。我一般会建至少两行权限一行给普通用户只读或可编辑一行给管理员允许删除。这里有一个细节如果普通用户不需要删除记录perm_unlink写0。否则用户可能在列表视图批量删除时把不该删的数据清掉。虽然Odoo有回收站机制但业务数据一旦误删恢复起来很麻烦。4.2 记录规则控制行级可见性CSV权限控制的是“能不能访问这个模型”而记录规则ir.rule控制的是“能访问这个模型里的哪些行”。这两个概念很容易混淆。简单来说CSV权限是粗粒度门禁记录规则是细粒度门禁。例如课程管理中讲师只想看到自己负责的课程可以这样定义record idrule_training_course_teacher modelir.rule field namename讲师只能看自己负责的课程/field field namemodel_id refmodel_training_course/ field namedomain_force[(teacher_id, , user.id)]/field field namegroups eval[(4, ref(base.group_user))]/ /record这里user.id是写死在规则里的特殊变量Odoo解析时会把当前登录用户替换进去。过滤器、看板、列表都会自动带这个条件。视图层加了这条规则之后普通用户看数据就等于每一条SQL查询都自带了一个不可见的WHERE条件。但是要注意记录规则写得太死也容易坑人。比如管理员也属于base.group_user如果规则对所有人生效管理员看全局数据反而要额外绕过很容易让人不明所以。我的习惯是单独建一个“讲师”权限组把这条规则只挂在该权限组上普通管理员不受影响。4.3 改视图不刷新先想想模块有没有升级“为什么我改了XML界面一点变化没有”这个问题几乎每周都会出现在开发者群里。Odoo的视图文件不是改完立刻生效的它是在模块升级时重新加载的。如果你只是在文件系统里改了XML但没有到“应用”页面升级对应模块系统里存储的视图记录仍然是旧版本。升级模块的正确姿势是先停掉可能导致冲突的测试操作在后台的“已安装的模块”里找到你的模块点击升级。升级过程中Odoo会卸载并重新加载模块的data文件更新视图、菜单、权限和演示数据。有一个提升效率的小技巧如果你只改了视图不要直接升级包含很多演示数据的模块因为升级会把数据列表重跑一遍可能触发唯一性约束。你可以把演示数据单独放到data/demo_data.xml并在__manifest__.py中把demo键设为True这样只有勾选了“演示数据”的数据库才会加载。开发自己测试时逻辑更干净。5. 视图开发中必须收藏的排错手记5.1 白屏、路径错误、日志优先级视图出问题第一反应不要盯着界面看先去看服务器日志。Odoo在加载XML时如果遇到错误会在日志中抛出完整的异常栈。最常见的几种报错都很有辨识度Element field cannot be located in parent view这是继承视图里xpath写错了找不到对应的父节点。Invalid model training.course in field namemodel说明模型还没建立或者模块依赖顺序不对。Record not found引用了一个不存在的XML ID常见于视图ID拼写错误。看日志不要只看最后一行要找File xxx.py, line这类路径提示。它通常会准确告诉你哪个文件、哪个记录出了问题。5.2 xpath 继承的三种正确姿势视图继承是Odoo里复用功能最核心的手段但也是最容易犯错的地方。继承视图时inherit_id指向被继承的视图arch里用xpath定位插入点。我的经验是先打开被继承视图的原XML确认父节点再写表达式。record idview_training_course_form_inherit modelir.ui.view field namenametraining.course.form.inherit/field field namemodeltraining.course/field field nameinherit_id refview_training_course_form/ field namearch typexml xpath expr//group/group[2] positioninside field namecolor/ /xpath xpath expr//header positioninside button nameaction_archive typeobject string归档/ /xpath /field /recordposition有几种取值inside是放入选中节点内部末尾after是放到选中节点后面before是前面replace是替换attributes是修改属性。我建议先用inside和after两种就够解决大部分场景其他少用。还有一个关键技巧同名视图可以同时存在多份继承不要担心覆盖。Odoo的最终展示视图是“基础视图 所有继承视图”按ID顺序合并后的结果不是后一个覆盖前一个。5.3 用超级用户和权限组分别测试视图在视图开发后期我有一个固定习惯切换成超级用户身份、带限制的普通用户身份各看一遍页面。因为很多“视图显示不对”并不是架构错误而是当前用户没有对应权限组导致字段被前端自动隐藏了。具体操作是在用户页面新建一个测试用户只勾选基础权限组然后打开模块看看菜单是否可见、字段是否可编辑。如果字段在管理员账号下正常在测试用户下消失问题通常出在groups属性上。视图里的字段可以这样限制field nameprice groupsbase.group_system/这句的意思是只有系统管理员能看见这个字段。这种配置常用于“成本价”“折扣率”等敏感字段。如果测试用户看不见大概率就是groups设置导致而不是前端渲染问题。5.4 只更新安全文件时避免全量升级很多人都在后台点“升级”按钮但如果每次只是加了一条访问权限记录全量升级会把所有视图重新载入一遍耗时也容易引入无关问题。有一个更精准的加载方式先进入“技术”菜单下的“外部标识”页面确认CSV里的模型ID再用开发者模式下的“更新应用”列表。其实最简单可控的办法是在命令行执行模块升级的特定操作或者直接把CSV文件内容手动改到数据库里再重启服务。这个话题有点深入但如果你负责一个大型生产库我强烈建议掌握“只加载某个XML数据”的命令而不是动不动全量升级。日常开发阶段可以随意升级到了生产环境就要慎之又慎。视图层的问题绝大多数可以在测试库解决不要拿生产库当试验田。6. 把视图层再往后推一步视图层做到这里你已经可以用一个自定义模型搭出列表、表单、看板、搜索视图再配上动作和菜单形成完整的操作闭环。接下来值得花时间的是把视图里的数据能力做深。比如给看板卡片加一个小图表或者把表单里的字段按业务阶段做动态显隐。这些都可以通过视图属性配合模型字段完成不需要写前端框架代码。Odoo的视图层本质上是配置驱动的你掌握的原则越多越能组合出灵活的功能。我个人在项目里的体会是先把最常用的三类视图做扎实比追求花哨的看板样式更实在。等你在项目里真正跑过一遍“建模-视图-菜单-权限-升级排错”的完整流程后续再接触报表视图、仪表盘视图就会发现那些不过是同一套规则的延伸。补充一个小技巧开发时给每个视图都写清楚name别偷懒让它自动生成。这个 name 在系统里显示为视图的技术名称后期排查问题时你能一眼看出是哪条记录。视图名尽量体现“模型用途视图类型”比如training.course.list、training.course.kanban一看到就知道是给哪个模型哪个模式用的。这一讲先到这里。下一讲如果继续做这个培训中心模块可以把报名记录、课程评价这些关联业务串起来那又会遇到新的视图布局问题。到那一步你再回头看今天这些配置会发现视图层其实是一种通用的表达语言只是入口和组合方式不同罢了。

关于恒美微站

恒美微站专注于为个体商户、工作室提供极简自助建站服务,让每个人都能轻松拥有专业网站。

快速链接

  • 关于我们
  • 建站服务
  • 主题模板
  • 案例展示
  • 资讯中心

服务项目

  • 可视化建站
  • 拖拽编辑
  • 主题定制
  • SEO 优化
  • 网站托管

联系方式

  • 📍 地址:北京市朝阳区建国路 88 号
  • 📞 电话:400-888-8888
  • ✉️ 邮箱:info@hmyw.cn
  • 🕐 时间:周一至周日 9:00-18:00

© 2024 恒美微站 hmyw.cn 版权所有 | 京 ICP 备 12345678 号