在这篇教程里咱们将会了解到 Odoo 模型里的一些其余类型的字段和特殊机制,而我依然会继续带领你们一块儿完善咱们的 Todo 应用,不断地往里面添加一些新的功能特性,让它看起来更丰满也更实用一些。python
在上一篇教程中,咱们已经建立好了待办事项的模型,可是只是添加了「描述」和「已完成?」两个字段,这确定是不能知足咱们的需求的。如今咱们来给待办事项增长一个「紧急程度」的字段,用来表示当前任务的优先级。git
# models.py class TodoTask(models.Model): _name = 'todo.task' _description = '待办事项' name = fields.Char('描述', required=True) is_done = fields.Boolean('已完成?') priority = fields.Selection([ ('todo', '待办'), ('normal', '普通'), ('urgency', '紧急') ], default='todo', string='紧急程度')
咱们添加了一个 Selection
类型的字段 priority
,而且指定了三个可供选择的程度类型,通常状况下,若是一个字段只有固定的几种可选值,一般都会选择使用 Selection
字段,它接受一个元组列表做为参数,其中元组的组成为 (value, string)
,左边的是数据库中存储的值,右边的是一个用于界面显示的描述。github
此处咱们还给这个字段添加了默认值 todo
,表示当一个待办事项被建立后,若是没有指定紧急程度,将默认是待办状态。咱们能够为任意类型的字段添加默认值。shell
在上一篇教程中咱们提到过,在对模型进行改动以后,须要对模块进行升级才能看到变动后的样子,除了从应用列表中找到模块进行升级外,咱们还能够在命令行中给 Odoo 的启动命令加上参数 -u todo
指定升级 todo 模块。数据库
./odoo-bin --addons-path=addons,../mymodules --db-filter=^demo$ -d demo -u todo
升级后建立或打开任意一条待办事项进入到表单页面,就能够看到已经多了「紧急程度」这个字段了,而且默认选择了「待办」这一状态。小程序
咱们已经给待办事项加上紧急程度了,但是光有这个还不够,咱们还要给它加上截止时间,毕竟 deadline 是第一辈子产力呀!api
# models.py deadline = fields.Datetime(u'截止时间')
咱们把截止日期也放到 TreeView 中,方便查看各个任务的 deadline微信
<!-- views.xml --> <field name="arch" type="xml"> <tree string="Todo"> <field name="name"/> <field name="deadline"/> <field name="is_done"/> </tree> </field>
不少时候咱们会须要用不一样的颜色对待办事项进行标记,例如咱们会但愿已通过期的任务以红色标记来提醒咱们,这个任务过时了。任务是否已通过期,咱们要先知道任务的截止时间(上面一小节已经加上了)和当前时间,而后进行比较判断任务的截止时间是否小于当前时间,若是是则表示任务已通过期了,咱们须要在视图上用红色将对应的任务标记起来。那将这个需求转化成代码应该怎么作呢?ui
这个需求跟时间有关,而且时间是流动(一直在变化)的,因此咱们应该要有一个方法在用户每次打开待办事项以前,把这个结果计算好,而且反馈给用户,还好 Odoo 的 ORM 已经为咱们实现了相关的机制——计算字段(Computed fields
)spa
# models.py is_expired = fields.Boolean(u'已过时', compute='_compute_is_expired') @api.depends('deadline') @api.multi def _compute_is_expired(self): for record in self: if record.deadline: record.is_expired = record.deadline < fields.Datetime.now() else: record.is_expired = False
计算字段其实和其余字段同样,只不过多了一个 compute
属性,它的值是计算这个字段值的方法名。咱们来看一下对应的方法 _compute_is_expired
头顶上的 @api.depends
这个装饰器,它接受了一个参数 deadline
,表示的是 is_expired
这个字段的计算会用到 deadline
这个字段的值(咱们须要用它的值和当前时间进行比较),若是一个计算字段会用到多个其余字段的值,这里就须要以逗号分隔,将用到的值的字段名依次传入装饰器中。
而 @api.multi
则表示该方法中的 self
是一个记录集(多个实例的集合),若是不理解,能够暂时不深究,到后面天然会知道这里的实际用法。
再来看看实际的计算逻辑部分,只有一个循环以及一条赋值语句,刚刚已经提到过这里的 self
表示一个记录集,咱们须要对这个记录集里的每一条记录进行计算,判断这个待办事项是否已通过期,这里的 record
就是每一条记录的实例对象,咱们用这条记录的 deadline
的值和当前时间 fields.Datetime.now()
进行比较,而后将结果赋值给字段 is_expired
,就是这么简单。
PS: 这里咱们对 deadline
进行了判断,是由于若是没有设置截止时间,又或者是在新建代办事项时,这里的 deadline
会是一个布尔值,是不能和时间字符串进行比较的。
其中你们可能会有疑问的应该是当前时间的获取,为何不是用 datetime.now()
吧?实际上获取当前时间用的也是这个方法,只不过 Odoo 的 ORM 替咱们封装了一层,fields.Datetime.now()
是类 Datetime
的静态方法:
# fields.py class Datetime(Field): type = 'datetime' column_type = ('timestamp', 'timestamp') column_cast_from = ('date',) @staticmethod def now(*args): """ Return the current day and time in the format expected by the ORM. This function may be used to compute default values. """ return datetime.now().strftime(DATETIME_FORMAT)
好的,这里先不过多纠结细节问题,如今咱们已经能够计算出来每一个待办事项是否已通过期了,那要怎么去用这个计算字段呢?咱们打开视图文件来加点东西上去:
<!-- views.xml --> <field name="arch" type="xml"> <tree string="Todo" decoration-danger="is_expired"> <field name="name"/> <field name="deadline"/> <field name="is_done"/> <field name="is_expired" invisible="True"/> </tree> </field>
在视图中咱们把 is_expired
字段加了进去,而且还加上了属性 invisible
,这个属性的做用是将当前字段隐藏起来,由于这里咱们不但愿用户看到这个字段的值,而是将结果反映在颜色上。而后咱们再看到 <tree />
标签多了一个属性 decoration-danger
,这个属性能够接受表达式或字段名做为值,当结果为真时,这个属性就会生效,将 TreeView 中知足表达式的行以红色标记,实际的效果以下:
今天这篇教程的内容就先到这里了,下一篇再继续带你们深刻更多的内容。这篇教程中的代码一样会更新在个人 GitHub
仓库中。
仓库地址:Odoo-Tutorial-Demo
距离上一次更新,已通过了好几个月了,这段时间除了忙公司的事情,还额外在作一些别的东西,而后最近在开发一个小程序。一直很想抽空出来更新这个系列的教程,一边又有不少事情在忙,拖更了实在是抱歉了!
若是你有任何的疑问,欢迎留言,我将会尽快给出答复,若是想要加群或者加好友,能够发送站内信给我,我会回复你微信号~
期待下一篇教程能够继续和大家见面。