很早之前,在博客园的文章中曾经介绍过Relax NG,如今odoo发展到了12.0,13.0时代,重新梳理一下有关Relax NG的知识点。
Relax NG是什么
Relax NG 是 REgular LAnguage for XML Next Generation的缩写,即“可扩展标记语言的下一代正规语言”,是一种基于语法的可扩展标记语言模式语言,可用于描述、定义和限制 可扩展标记语言(标准通用标记语言的子集)词汇表。简单地说 Relax NG是解释XML如何被定义的一套XML。Odoo就是通过定义了一套rng文件定义了自己一套xml框架结构,在模块被安装或者升级的时候将其解析成与之相对应的内置对象,存储在数据库中。关于Relax NG的语法规则,可以参考Relax NG的官网。
Relax NG语法
我们可以结合odoo中的一个Relax NG例子来看一下:
1 | <rng:define name="data"> |
这是我们常用的odoo视图文件中的data节点的结构。
- define 定义一个节点,方便引用。
- zeroOrMore 表示接受零个或多个节点。
- choice 表示在列表中选择。
关于Relax NG更多介绍,请参见官方网站
odoo解析Relax NG
模块安装时
模块在安装时,odoo会解析xml文件是否符合既有的xml架构,解析方法使用的是odoo.tools.convert.py中的convert_xml_import方法:
1 | def convert_xml_import(cr, module, xmlfile, idref=None, mode='init', noupdate=False, report=None): |
从上面的代码中可以看出,解析的文件是import_xml.rng,由此文件我们可以看到我们xml经常碰到的老朋友们:
1 | ... |
由此文件,我们可以总结出xml可以出现的一级节点列表:
menuitem
- id(必填)
- name
- parent
- action
- sequence
- groups
- icon
- web_icon
- web_icon_hover
- string
record
- id(可选)
- forcecreate(可选)
- model
- context(可选)
- 子节点:field(可多个)
template
- id
- t-name
- name
- forecreate
- context
- priority
- inherit_id
- primary
- groups
- active
- customzie_show
- page
delete
- model
- id
- search
act_window
- id
- name
- res_model
- domain
- src_model
- context
- view_id
- view_type
- view_mode
- multi
- target
- key2
- groups
- limit
- usage
- auto_refresh
url
- id
- name
- url
- target
assert
- model
- search
- count
- string
- id
- context
- severity
- test
report
- id
- string
- model
- name
- report_type
- multi
- menu
- keyword
- rml
- file
- sxw
- xml
- xsl
- parser
- auto
- header
- webkit_header
- attachment
- attachment_use
- groups
- usage
workflow
- model
- action
- uid
- context
- ref
- value
function
- model
- name
- id
- context
- eval
ir_set
- 子节点:field
这就解释了,笔者曾经的困惑,xml中为什么可以出现act_window这样一个节点?menuitem是在哪里定义的?
视图渲染时
上面提到的只是对静态代码的约束,我们知道,odoo中非常有特点的功能就是可以在界面中编辑xml代码,那么,odoo又是如何确保用户手动填写的代码符合Relax NG架构的呢?
经过几番跟踪测试,我们发现,当odoo渲染页面视图时,会调用tools.view_validation中的relaxng方法:
1 | def relaxng(view_type): |
从上述方法中可以看出,每种视图都要经过验证,只有符合定义的属性才会通过。定义的文件位于base模块下的rng文件夹中。这里包含了我们经常用到的search、tree、pivot、graph、gantt、diagram、calendar等视图的结构文件。
自定义视图架构
了解了视图架构的验证机制,那么我们自然就想到了可以拓展视图的架构。最简单的方法莫过于直接修改RNG文件,但是这样污染了源代码。
想要避免修改源码的方法也很简单,重载relaxng方法,使之先查找自定义的RNG文件夹,如果找不到再去base模块查找。例如,笔者为了禁止日历视图拖拽,编写了一个calendar_draggle模块,其中就新增了一个draggable属性而没有修改RNG源文件:
1 |
|