7.Odoo开发基础: 工作计划模块第一谈
这个例子来自Daniel Reis的《Odoo Development Essentials》一书,之所以也加进来是因为我觉得学习框架是例子越多越好,然后这本书我是在 这个网站 限时观看的,也是为了保留有价值的信息吧。
我们这次要创建的模块的功能是进行工作计划管理,也就是常说的"to do task",
首先是 __init__.py
文件:
# -*- coding: utf-8 -*- from .models import main_model
然后是 __openerp__.py
文件:
# -*- coding: utf-8 -*- { 'name': "todo task app", 'summary': """ 工作计划管理系统 """, 'description': """ 工作计划管理系统: 安排你的工作计划。 """, 'author': "wanze", 'website': "http://www.yourcompany.com", # Categories can be used to filter modules in modules listing # Check https://github.com/odoo/odoo/blob/master/openerp/addons/base/module/module_data.xml # for the full list 'category': 'Test', 'version': '0.1', # any module necessary for this one to work correctly 'depends': ['mail'], # always loaded 'data': [ 'security/ir.model.access.csv', 'views/views.xml', ], # only loaded in demonstration mode 'demo': [ # 'demo.xml', ], 'application' : True, }
注意到depends设置为了mail模块,因为等下to do task子菜单要在消息子菜单中显示的,其是由mail模块设置的。然后同样加载了views.xml文件,还有设置访问权限的ir.model.access.csv文件等下再说。
然后我们再来看 main_model.py
文件
from openerp import models, fields, apiclass TodoTask(models.Model):_name = 'todo.task'name = fields.Char('Description',required=True)is_done = fields.Boolean('Done?')active = fields.Boolean('Active?', default=True)@api.onedef do_toggle_done(self):self.is_done = not self.is_donereturn True@api.multidef do_clear_done(self):done_recs = self.search([('is_done', '=', True)])done_recs.write({'active': False})return True
读者现在应该很清楚这些代码在做什么了,其中fields.Boolean定义了一个布尔值字段,然后我们看到第一个可选参数默认就是 string ,就可以直接写上。然后 default 是来设置该字段的默认值的。
下面定义的两个方法和等下form视图下的两个按钮相关,这里用到了Odoo新的ORM API,使用了@api.one @api.multi
这样的装饰器。 值得一提的是,可被用户调用的方法,比如这里的按钮是被用户点击才调用的, 都需要一个返回值 ,否则XMLRPC协议无法正常工作,实在没啥好返回的,就return True
。
- @api.multi
- 默认的装饰器是这个,没有自动迭代recordset,因为它默认接受的self就是recordset对象(所有recordset就是指相同模型下的所有对象,或者说同一SQL表格下的所有记录。)。
- @api.one
- @api.one装饰器将会自动产生一个迭代动作,具体是指迭代某一recordset,然后其内的self就是一个record也就是该模型下SQL表格的一条记录。然后@api.one返回的是一个列表值,某些网络客户端可能并不支持这点。所以还是尽量少用@api.one。
具体 views.xml
文件的内容如下所示:
<?xml version="1.0"?><openerp><data><!-- Action to open To-do Task list --><act_window id="action_todo_task"name="To-do Task"res_model="todo.task"view_mode="tree,form" /><record id="view_form_todo_task" model="ir.ui.view"><field name="name">To-do Task Form</field><field name="model">todo.task</field><field name="arch" type="xml"><form><header><button name="do_toggle_done" type="object"string="Toggle Done" class="oe_highlight" /><button name="do_clear_done" type="object"string="Clear All Done" /></header><sheet><group name="group_top"><group name="group_left"><field name="name"/></group><group name="group_right"><field name="is_done"/><field name="active" readonly="1" /></group></group></sheet></form></field></record><record id="view_tree_todo_task" model="ir.ui.view"><field name="name">To-do Task Tree</field><field name="model">todo.task</field><field name="arch" type="xml"><tree colors="gray:is_done==True"><field name="name"/><field name="is_done"/></tree></field></record><record id="view_filter_todo_task" model="ir.ui.view"><field name="name">To-do Task Filter</field><field name="model">todo.task</field><field name="arch" type="xml"><search><field name="name"/><filter string="Not Done"domain="[('is_done','=',False)]"/><filter string="Done"domain="[('is_done','!=',False)]"/></search></field></record><!-- Menu item to open To-do Task list --><menuitem id="menu_todo_task"name="To-Do Tasks"parent="mail.mail_feeds"sequence="20"action="action_todo_task" /></data></openerp>
有了前面的基础,这个文件虽然看上去有点复杂,但我们应该是已经能够看出点端倪出来了的。首先我们不管视图那块,看到act_window和munuitem,我们看到这个菜单项设置的父菜单是mail.mail_feeds
,
parent="mail.mail_feeds"
因为对Odoo官方模块还不是很熟悉,但我们根据后面的显示效果,如下图所示:
我们可以推断这个父菜单 mail.mail_feeds
就是上图箭头所指的那个菜单。
然后我们看到tree视图,其中有这么一行:
<tree colors="gray:is_done==True">
这种语法还不太熟悉,但大体意思就是如果该模型下的某个对象 is_done
的值为True,则颜色设置为灰色。
然后值得一提的是,这里的search视图,并不需要在前面的动作对象的view_mode属性上加上,其更像是tree视图的增强功能,在搜索框那里,你点击才能看到。代码中唯一的难点就是domain过滤器的语法,这里先略过,后面再讨论吧。
然后我们再看到form视图,具体显示效果如下所示:
<sheet> <group name="group_top"> <group name="group_left"> <field name="name"/> </group> <group name="group_right"> <field name="is_done"/> <field name="active" readonly="1" /> </group> </group> </sheet>
这里代码如何利用group来布局要好好体会一下,然后field标签这里又出现了一个新的属性readonly ,这样这个字段的值就不能更改了。
7.1 数据访问权限管理
Odoo对于其内的数据访问权限管理有两种机制: 一种是模型访问权限管理(access rule);第二种是记录规则管理(record rule)。其中record rule可以看作在access rule之上的更进一步细化。如果什么访问规则都不设定的话,那么默认只有Administrator才能访问这个模型的数据,其他的用户都不能访问。Odoo的安全机制是通过群组(group)来管理的,然后record rule对Administator用户是无效的,而access rule还有效。
https://www.odoo.com/forum/help-1/question/is-it-possible-to-manage-record-based-access-control-2597
7.1.1 access rule
访问权限控制一般是用security文件夹下的 ir.model.access.csv
文件来管理的。这个csv文件的表头是:
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
我们这里定义的模型名字是 todo.task
,其对应的 model_id
就是 model_todo_task
。这个是规定死了的,然后其他的id, name名字可随意。一般id就是在模型名字前加个access即 access_todo_task
,然后name更随意了,似乎我看到空格都可以的,但一般就简单把对应的模型的名字放进去即可,即todo.task
。然后第四个是群组id,接下来就是读权限,写权限,创建权限和删除权限,用0表示无权限,1表示有权限,具体要根据需要来设置权限。
下面是todo_app模块的 ir.model.access.csv
详情:
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink access_todo_task,todo.task,model_todo_task,base.group_user,1,1,1,1
The default policy is DENY
这里的base.group_user群组参考资料4说雇员群组属于base.group_user群组,这里不太清楚,如果实在不确定这个值省略不填也是可以的。
7.1.2 record rule
这样设置之后每一个登录Odoo用户写的todo task其他人都可以看到,这显然不太好。进一步我们可以用record rule来对具体的record记录进行筛选。
在security文件夹里新建一个 todo_record_rules.xml
文件,文件内容如下:
<?xml version="1.0" encoding="utf-8"?><openerp><data noupdate="1"><record id="todo_task_user_rule" model="ir.rule"><field name="name">ToDo Tasks only for owner</field><field name="model_id" ref="model_todo_task"/><field name="domain_force">[('create_uid','=',user.id)]
</field><field name="groups" eval="[(4,ref('base.group_user'))]"/></record></data></openerp>
这些record rule记录是 ir.rule
模型,存储在 public.ir_rule
表格里面的。name属性就不多说了,应该很熟悉了。然后 model_id
属性对应的就是某个模型,而 domain_force
就是对该模型中所有记录进行某种过滤操作,
The default policy is ALLOW,so by default any operation will be refused if the user does not explicitly have the right to perform it via one of her groups' access rights.
The default policy is ALLOW, so if no rule exists for a given model, all documents of that model may be accessed by users who have the necessary access rights. 然后 groups
字段还看不太懂。我看了一下 ir_rule
表格,似乎没有groups这个属性,这里的细节先略过吧。
data标签这里有个 noupdate 属性,如果设置为"1",则意思是本模块升级不更新本数据,如果设置为"0"则更新本数据。
然后我还发现一个问题: 那就是我中途试验过一个不加载这个xml文件的版本,数据库里面还是保存着这条记录,然后我手动删除SQL数据库的这条记录才行,后来又试验加载这个xml文件的版本,数据库这个权限记录加载不上去。然后我发现如果删除模块,则数据库里面的这条记录才会被删除了。然后再重新安装本模块,则这条权限记录才会被更新上去。也就是说目前的Odoo框架升级对于record rule支持并不是很好,在这方面要小心。
经过这样的配置之后,除了Administrator用户可以看到所有人的todo task之外,其他人都只能看到和编辑自己的todo task了。