Odoo视图的基本组件
前言
本文讲述的是一个数据模型创建完成之后,展示给用户的东西。所以本文提到的视图的基本组件就是做数据记录展示的表格、数据记录新增修改时的表单以及搭配数据表格使用的搜索框。
前期代码准备
先创建一个模型新生报到的模块,定义好模型字段以及相应的配置。
创建模块:
odoo-bin文件所在目录下打开cmd,输入以下命令:
python odoo-bin scaffold student myaddons
scaffold命令用于创建模块,后面的两个参数依次是模块名称、模块存放路径。路径不存在则回自动创建同名目录,但是需要注意的是新创建的模块存放目录需要将路径添加到conf文件中,在odoo.conf文件下有一个addons_path变量表示模块或应用的路径,路径可以有多个,多个路径之间用逗号隔开。
创建模型:
在执行完上面的命令后,myaddons目录下就会多出一个student目录,这就是我们创建的模型,这个目录下就已经为我们创建好了模型目录models和视图目录views。这里先说models目录,这个目录下就是用于存放定义模型的代码,有多个文件时需在__init__.py文件中导入全部模型类,这里偷个懒,直接使用现成的models/models.py文件
# models/models.py
from odoo import models,fields,api
# 定义模型类
class Student(models.Model):
_name = "student.student" # 模型名称,通常为模块名.模型类名。其他地方可以通过这个名称指向这个模型
_description = "student.student" # 描述,在这里不重要
# 定义字段
name = fields.Char(string="姓名")
specialty = fields.Char(string="专业")
student_num = fields.Char(string="学号")
check_in = fields.Boolean(string="是否已报到")
模块配置文件:
odoo中的所有视图都是以xml文件存放在views目录下的,所以我们编辑odoo视图实际上就是编辑xml数据,然后odoo框架回自动将这些数据渲染成对应的视图或组件。这里先sutdent/views目录下创建一个student_view.xml文件,然后将这个文件配置到__mainfest__.py文件中。
每个模块目录下都有一个__mainfest__.py文件,它是该模块的配置文件,打开这个文件找到data属性,将我们自定义的视图文件路径添加到里面:
{
……
"data":[
'security/ir.model.access.csv', # 权限文件
'views/views.xml',
'views/templates.xml',
'views/student_view.xml',
]
}
在这里一个空白的模块就算是创建完成了,在odoo前端页面中点击应用,搜索这个模块点击激活就可以。如果应用里找不到的话,odoo可以切换成开发者模式然后应用页点击更新应用列表,之后再搜索一般就能找到了
编辑模块视图最基本的窗口信息:
在默认创建的views/views.xml文件中,scaffold命令已经帮我们创建好了常用的窗口动作、菜单选项的组件,打开注释稍微改一下就可以用:
<odoo>
<data>
<!-- 动作窗口 -->
<record model="ir.action.action_window" id="student.action_window">
<field name="name">新生入学信息</field>
<!-- 选择数据模型 -->
<field name="res_model">student.student</field>
<!-- 需要展示的视图,逗号后面不要有空格 -->
<field name="view_mode">tree,form</field>
</record>
<!-- 菜单选项 -->
<menuitem name="新生入学信息" id="student.menu_root" />
<!-- parent属性用于指向父级部件,action属性确定动作窗口 -->
<menuitem name="新生入学信息" id="student.menu_1"
parent="student.menu_root"
action="student.action_window"
/>
</data>
</odoo>
视图文件里的内容有修改时,都需要在odoo前端页面上对模块做一次升级。具体步骤:
- 前端页面点击应用
- 应用页面找到对应模块
- 点击模块卡片右上角三个点,里面有个升级选项,点击即可
数据表格 tree
数据表格是前端展示数据记录的部件,odoo中用tree表示数据表格类型,实际上我们基本的数据表格操作就是设置展示哪些数据字段
<!-- student_views.xml -->
<odoo>
<!-- odoo视图的固定写法,最外层odoo标签,每个部件或者每个视图数据就是一个record标签 -->
<!-- model='ir.ui.view'表示是一个视图部件 -->
<record model="ir.ui.view" id="student.list">
<field name="name">新生入学信息</field>
<field name="model">student.student</field>
<field name="arch" type="xml">
<!-- 在name="arch"的标签创建tree表示这是一个数据表格部件,表单、搜索框同理 -->
<tree>
<!-- 设置展示字段 -->
<field name="name" string="姓名" />
<field name="student_num" string="学号" />
<field name="specialty" string="专业" />
<field name="check_in" string="是否报到" />
</tree>
</field>
<record>
<odoo>
odoo视图文件中的所有内容都必须在odoo标签以内,早期的odoo版本里,odoo标签下还必须有一个data标签,我们写的每一个部件或者其他内容就是一个完整的record标签,放在data标签之下,这是odoo的标准写法,现在新的版本可以不写data标签。
record中model属性指明整个标签是干啥的,是UI部件还是action动作亦或者其他什么,有点类似html中input标签的type属性。id属性同html中的id属性,是标签的标识而不是数据记录的id。field标签中的name属性与record标签model属性同理,这里的field标签和模型中的字段关系不大,只是record标签中的一个子元素
搜索框search
一般odoo都有提供默认的搜索框部件,在搜索框中输入文本后,搜索框会拿着文本去与数据表格展示的第一个字段匹配。能匹配到下方的数据表格就展示匹配到的内容,没匹配到下方数据表格就没有数据。如果搜索框输入的是字符类型匹配方式就是模糊匹配,类似sql语句中的like;如果输入的数字匹配方式就是精准匹配,类似sql语句用的=
自定义搜索框能做的有三种:
- 用户在搜索框输入内容后,可以匹配指定的字段
- 自定义个筛选条件,用户点击后直接筛选出对应的数据记录
- 自定义group_by分组字段,用户选择后按选择的字段分组
<!-- student_view.xml -->
<odoo>
……
<record model="ir.ui.view" id="student.search">
<field name="name">搜索框</field>
<field name="model">student.student</field>
<field name="arch" type="xml">
<search string="自定义搜索工具">
<!-- 设置检索的字段 -->
<field name="name" />
<field name="student_num" />
<field name="specialty" />
<!-- 添加筛选项 -->
<!-- name属性必须要有,否则会报错 -->
<!-- domain属性为筛选条件,可以多个,每个筛选条件放在一个小括号中,格式为:(字段名,条件运算符,值) -->
<filter string="所有李姓同学" name="like_li" domain="[('name','like','李%')]" />
<filter string="已经报到的学生" name="check_in" domain="[('check_in','=',True)]" />
<!-- 添加分组项 -->
<group string="自定义分组">
<!-- 分组条件写在context中 -->
<filter string="是否已报到" name="by_check_in" context="{'group_by':'check_in'}" />
<filter string="专业" name="by_specialty" context="{'group_by':'specialty'}" />
</group>
</search>
</field>
</record>
</odoo>
上述代码的分组条件中,我们看似每次只以一个字段作为分组条件,不能像pandas那样同时按多个字段分组,实际上用户在数据表格页面的分组按钮下是可以多选分组条件的,odoo会按照用户选择字段的顺序做多级分组
表单 form
<!-- student_views.xml -->
<odoo>
……
<record model="ir.ui.view" id="student.form">
<field name="name">新生入学信息</field>
<field name="model">student.student</field>
<field name="arch" type="xml">
<form string="新生入学信息">
<sheet>
<!-- 所有的字段都是放在group标签下的 -->
<group>
<field name="name" />
<field name="checkin" />
</group>
<notebook>
<page string="学籍信息">
<group>
<field name="specialty" string="专业" />
<field name="student_num" string="学号" />
</group>
</page>
</notebook>
</sheet>
</form>
</field>
</record>
</odoo>
和前面的数据表、搜索框一样,表单form标签也是创建在一个name属性为arch的field标签下。最简单的布局方式就是在form标签下直接创建group标签,然后在其下添加field标签指明字段。group标签的作用类似于Bootstrap里的栅格,会默认填充上一级部件的全部宽度,所以添加一个sheet标签就是为了让表单里的内容能够布局在好看一点的衬布上,而不是填充整个页面。
同样的group标签也可以将上级部件的平均划分成指定数量的等宽的多个部件:
<!-- 字段以两列的布局呈现 -->
<group col='2'>
<group>
<field name="name" string="姓名" />
<field name="check_in" />
</group>
<group>
<field name="specialty" string="专业" />
<field name="student_num" string="学号" />
</group>
</group>
notebook标签会渲染成类似layUI框架里的选项卡,notebook标签下的每一个page标签都相当于一页卡片,能够展示不同的内容,通过string属性来指明标签或者部件展示出来的名称。
field标签中的string属性也是同理,用来展示表单输入框前的文本标签,相当于html中input标签前的label标签。字段field标签中的string属性可以不指定,这时表单将从数据模型中获取字段所对应的名称。