1.视图
通用格式:
<record model="ir.ui.view" id="view_id">
<field name="name">view.name</field>
<field name="model">object_name</field>
<field name="priority" eval="16"/>
<field name="arch" type="xml">
<!-- view content: <form>, <tree>, <graph>, ... -->
</field>
</record>
1.1 Tree视图
以表格形式展示需要展示的所有数据
1.2 Form视图
以一个模型(表)展示模型的数据,通常与sheet(页面模板)标签、group(页面块)标签配合使用
1.3 Search视图
搜索视图,通常结构是先写字段再写filter(过滤器),而过滤器又通常含有domain(域)和context(上下文)配合使用
1.4 Calendar视图(日历)
py文件中需要设置开始时间和结束时间及其方法,在xml中calendar标签中需要声明属性date_start、date_stop、color
1.5 Gantt视图(水平条形项目计划、进度)
1.6 Graph视图(图表)
1)Bar(default;条形图)
2)Line(折线图)
3)Pie(饼状图)
1.7 Kanban视图(组织发布任务或分阶段)
2.关系
2.1 关系(字段)类型--模型之间的关系
(1)One2many
定义:otm = fields.One2many('关联对象(模型名)', '关联字段', string=''...)
PS:One2many的关联对象,要在关联对象中Many2one回来,否则会报错,其他两种关系类型单独使用则不用
(2)Many2one
定义:mto = fields.Many2one('关联对象', string...)
(3)Many2many
定义:mtm = fields.Many2many('关联对象', '关联表/中间表', '关联字段1', '关联字段2', string...)
PS:其中关联表/中间表和关联字段可不填
2.2 属性关联字段
定义:related='所在模型的字段.该字段的关联模型的字段.该字段的关联模型的字段...'
通常与关系类型配合使用
如:两个模型a_model、b_model,a_model含有test1、rela,b_model中含有test2字段
rela = fields.Many2one('b_model', string='关联b')
test1 = fields.Float(related='rela.test2', string='关联test2')
3.继承
3.1 模型
3.1.1 在原有的模型中继承(不舍模型名,默认)
1)添加,字段或方法
2)覆盖,字段或方法
3)添加,约束或警告
3.1.2 创建新的模型中继承(设置模型名且与父模型名不同)
提供父记录的透明访问
3.2 视图(基本视图或报表继承)
例子:
<record id="idea_category_list2" model="ir.ui.view">
<field name="name">id.category.list2</field>
<field name="model">idea.category</field>
<field name="inherit_id" ref="id_category_list"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='description']" position="after">
<field name="idea_ids" string="Number of ideas"/>
</xpath>
<-- 或者用定位元素的写法 -->【但如果字段在同一视图中多次出现,则应始终使用XPath语法。】
<field name='description' position="after">
<field name="idea_ids" string="Number of ideas"/>
</xpath>
<-- end -->
</field>
</record>
PS:expr的内容是需要继承的元素,position是具体操作“(inside:添加属性),(replace:替换元素),(before:匹配元素前插入),(after:匹配元素后插入), (attributes:匹配元素更改属性)”
3.3 模板
3.3.1 视图类型的qweb文件继承
1)在statc/xml目录下新建一个xml文件
2)编写以下内容
#xml
<template id="唯一的id" xml:space="preserve">
<t t-extend="要继承扩展的template的name属性值">
<t t-jquery="使用选择器来定位" t-operation="相当于position">
//扩展的内容,一般用html语法+qweb语句编写
</t>
</t>
</template>
#manifest
"qweb": [
"static/src/xml/qweb_file.xml",
],
3.3.2 data类型的qweb文件继承
1)在views目录下新建一个xml文件
2)编写以下内容
#xml
<template id="唯一id" inherit_id="模块.继承的templateid">
<xpath expr="xpath定位语句">
//引入的内容,一般是link标签和script标签,把static/src目录下的css、js子目录的文件引入
</xpath>
</template>
#manifest
"data": [
"views/XXX.xml",
],
4.常用api
1) one: 用于self单一记录的情况
2) multi: 用于self指多个记录的合集
3) model: 此时的self仅代表模型本身,不含任何记录
4) contrains: 字段的代码约束
5) depends: 主要用于compute方法,depends就是用来标明该方法依赖于哪些字段的
6) onchange: 当字段发生改变时,触发绑定的函数方法
7) returns: 主要是用来指定返回值的格式,它接受三个参数,第一个是返回值的model,第二个是向下兼容的method方法,第三个为向上兼容的method方法
5.报表
5.1 设置基本参数
例:
<report
id="report_session"
model="openacademy.session"
string="Session Report"
name="openacademy.report_session_view" //模块名.模板id(必填)
file="openacademy.report_session" //模块名.模板id(用于更好地关联模板)
report_type="qweb-pdf" />
5.2 template模板(QWeb规则)
例:
<template id="report_session_view">
<t t-call="web.html_container">
<t t-foreach="docs" t-as="doc">
<t t-call="web.external_layout">
<div class="page">
<h2 t-field="doc.name"/>
<p>From <span t-field="doc.start_date"/> to <span t-field="doc.end_date"/></p>
<h3>Attendees:</h3>
<ul>
<t t-foreach="doc.attendee_ids" t-as="attendee">
<li><span t-field="attendee.name"/></li>
</t>
</ul>
</div>
</t>
</t>
</t>
</template>
5.3 QWeb常用指令
1) t-esc:输出数据
2) t-if、t-elif、t-else:条件判断
3) t-foreach:循环处理,通常与t-as使用,t-as用于表示foreach操作的模型的自定义名称
4) t-att-$name:设置属性($name为属性名如a、class、name)
需要写多个属性时 t-att=mapping
例如:<div t-att="{'a': 1, 'b': 2}"/>
#输出
<div a="1" b="2"></div>
也可以写成 t-att=pair
例如:<div t-att="['a', 'b']"/>
#输出
<div a="b"></div>
5) t-set:定义一个变量名,通常与t-value连用(也可不用,则需加入别的标签或值),t-value是用表达式来表示t-set的内容或值
6) t-call:用于调用其他模板
7) t-field:用于获取记录字段,但要注意不同模型的使用
8) t-options:用于自定义字段,最常用的是widget组件使用
例如:t-field-options='{"widget": "image"}'
6.权限
权限管理四个层次:
1.菜单级别:对用户是否隐藏菜单
2.对象级别:对表是否有“创建,读取,修改,删除”
3.记录级别:对自己或下级的访问权限,例如业务员对自己所创客户有访问权限,经理可以访问对管辖的业务员所有的客户对象
4.字段级别:一个对象或表上的某些字段的访问权限
1) 权限组建立
例:
<record id="base.group_hr_manager" model="res.groups">
<field name="name">Manager</field>
<field name="comment">the user will have an access to the human resources configuration as well as statistic reports.</field>
<field name="category_id" ref="base.module_category_human_resources"/>
<field name="implied_ids" eval="[(4, ref('base.group_hr_user'))]"/>
<field name="users" eval="[(4, ref('base.user_root'))]"/> //把admin用户加入该组中
</record>
@name: 用户组名,这个可以翻译的
@comment: 用户组的注释
@category_id: 用户组所属的模块名
@implied_ids(记录级别,上下级控制): 基于哪个用户组,这个层级关系 <field name="implied_ids" eval="[(4, ref('base.group_user'))]"/>是最基础的
用户名,最初是基于这个,后面一层一层递增,像上面 base.group_hr_user 定义时就是基于最基础
@users:预设用户属于这个用户组
2) 组控制菜单显示(菜单级别)
<record model="ir.ui.menu" id=" memu_id1">
<field name="name" >menu1</field>
<field name="groups_id" eval="[(6,0,[ref('A'),ref('B')]),]"/>
<field name="sequence">1</field>
</record>
@ name 菜单名称
@ groups_id 哪些组可以访问该菜单
@ sequence 该菜单的序号
这样A组与B组的成员都可以访问menu1菜单,menu1菜单的显示顺序为1
注:eval 后面解释,多个组访问用“,”隔开
<menuitem id="menu_id2 " name="menu2" parent="menu_id1" sequence="1" groups="A,B "/>
@ name 菜单名称
@ parent 父类菜单 如果没有可以不写parent
@ groups哪些组可以访问该菜单
这样menu1的子菜单menu2可以被A组合B组的成员访问
3) 规则建立(对象级别)
例:
<record model="ir.rule" id="rule1">
<field name="name">rule1</field>
<field name="model_id" ref="model_model1"/>
<field name="global" eval="True"/>
<field name="domain_force">[1,’=’,1]</field>
<field name="groups" eval="[(4,ref('A'))]"/>
</record>
@ name 规则名称
@ model_id 依赖的模块
@ global 是否是全局
@ domain_force 过滤条件
@ groups 属于哪个组
这样A组的成员就可以取到model_model1的所有数据
eval:
many2many
(0,0,{values}) 根据values里面的信息新建一个记录。
(1,ID,{values})更新id=ID的记录(写入values里面的数据)
(2,ID) 删除id=ID的数据(调用unlink方法,删除数据以及整个主从数据链接关系)
(3,ID) 切断主从数据的链接关系但是不删除这个数据
(4,ID) 为id=ID的数据添加主从链接关系。
(5) 删除所有的从数据的链接关系就是向所有的从数据调用(3,ID)
(6,0,[IDs]) 用IDs里面的记录替换原来的记录(就是先执行(5)再执行循环IDs执行(4,ID))
例子[(6, 0, [8, 5, 6, 4])] 设置 many2many to ids [8, 5, 6, 4]
one2many
(0, 0,{ values })根据values里面的信息新建一个记录。
(1,ID,{values}) 更新id=ID的记录(对id=ID的执行write 写入values里面的数据)
(2,ID) 删除id=ID的数据(调用unlink方法,删除数据以及整个主从数据链接关系)
例子:
[(0,0,{'field_name':field_value_record1,...}),(0,0,{'field_name':field_value_record})]
many2one的字段比较简单,直接填入已经存在的数据的id或者填入False删除原来的记录。
4)设置ir.model.access.csv (也相当于对象级别,设置某个组对某个模型的增删改查权限)
@id 随便取
@name 随便取
@model_id:id 这个就是你所定义的对象了
@group_id:哪个组
@perm_read","perm_write","perm_create","perm_unlink" 增删改查权限了。1代表有权限
5)字段级别
<field name="company_id" groups="base.group_multi_company" widget="selection"/>
隐藏技巧:
1)直接隐藏(所有人)
<group name="owner" position="attributes">
<attribute name="invisible">True</attribute>
</group>
2)满足某些条件隐藏
<xpath expr="//field[@name='parent_id']" position='attributes'>
<attribute name="attrs">{'invisible': [('passenger','=', True)]}</attribute>
</xpath>
3)通过组来隐藏
<xpath expr="//field[@name='type']" position="attributes">
<attribute name="groups">base.group_no_one</attribute>
</xpath>
4)菜单的隐藏
<record model="ir.ui.menu" id="crm.menu_crm_opportunities">
<field eval="[(6,0, [ref('base.group_no_one'),])]" name="groups_id"/>
</record>
5)字段显示权限,其他组则隐藏
<field name="company_id" groups="base.group_multi_company" widget="selection"/>
6)在model中判断
self.pool.get('res.users').has_group(cr, uid, 'sale.group_discount_per_so_line')
7.国际化
每个模块都可以在i18n目录中提供自己的翻译,方法是将文件命名为LANG.po,其中LANG是语言的语言环境代码,或者语言和国家/地区组合不同(例如pt.po或pt_BR.po)。Odoo将为所有启用的语言自动加载翻译。
更改翻译流程:创建目录 模块名/i18n/ -> 设置‣翻译‣导入/导出‣导出翻译(指定模块,导出翻译) -> 将导出文件放入创建目录 -> 更改翻译
msgid:为字段显示名称
mgstr:为翻译显示名称
8.向导
向导与其他的模型不同,其基类不是常见的Model而是TransientModel。
向导记录不是永久性的,会在一段时间后自动从数据库中删除,所以被称为瞬态
向导不需要访问权限,即用户拥有向导记录的所有权限
向导记录可以通过many2one字段引用普通记录或向导记录,但反之则不不行
9.网页服务(RPC)
XML-RPC
JSON-RPC
Odoo-RPC
10.消息机制
在模型中整合消息系统是很简单的,只需要从mail.thread继承模型并将对应的字段和widget添加到视图中就可以了。
例如:
#model
_inherit = ['mail.thread']
#view
<field name="message_ids" widget="mail_thread"/>
1.发布消息
* message_post(self, body='', subject=None, message_type='notification', subtype=None, parent_id=False, attachments=None, content_subtype='html', **kwargs)
在一个会话列表中发布一条新消息,返回新的mail.message ID
* message_post_with_view(views_or_xmlid, **kwargs)
发送一条使用指定id对应视图进行渲染的消息。这个方法只能单独使用。
* message_post_with_template(template_id, **kwargs)
使用模板来发送消息
2.接收消息
* message_new(msg_dict, custom_values=None)
当收到的消息不属于一个已存在的讨论列表时由message_process调用,默认是基于相关的模型创建一个新讨论记录,其邮件内容直接被提取用于创建新记录,可以通过覆盖该方法来添加新特性。
* message_update(msg_dict, update_vals=None)
当一个收到已存在的讨论列表的消息时由message_process调用,默认用邮件里的update_vals来更新记录。可通过覆盖方法来添加其他特性。
3.关注者管理
* message_subscribe(partner_ids=None, channel_ids=None, subtype_ids=None, force=True)
添加参与者
* message_subscribe_users(user_ids=None, subtype_ids=None)
将message_subscribe封装,只是用用户替代partner
* message_unsubscribe(partner_ids=None, channel_ids=None)
将合作伙伴从记录的订阅列表移除
* message_unsubscribe_users(user_ids=None)
封装message_unsubscribe,用user替代partner
- 记录变化 --
为了对字段进行监听,只需要将track_visibility 属性设置为onchange(当字段值改变时展示在通知中),
always(该值总是会被显示在通知中,一般用于让通知内容更好理解)