(05)odoo数据库和业务操作

摘要:
从一个示例*To do wizard#configuration file__openerp_开始。py:{‘name’:‘To-doTasksManagementAssistant’,‘description’:‘MassedityourTo-Dobacklog.’,‘author’:“DanielReis”,‘depends’:[‘To_user’],‘data’:[’To_wizard_view.xml‘],}__ini

以一个例子开头
* To-do 向导
# 配置文件
__openerp_.py:
{ 'name': 'To-do Tasks Management Assistant',
'description': 'Mass edit your To-Do backlog.',
'author': 'Daniel Reis',
'depends': ['todo_user'],
'data': ['todo_wizard_view.xml'], }
__init__.py:
from . import todo_wizard_model
# 模型 todo_wizard_model.py
# -*- coding: utf-8 -*-
from openerp import models, fields, api
from openerp import exceptions # will be used in the code

import logging
_logger = logging.getLogger(__name__)

class TodoWizard(models.TransientModel):
_name = 'todo.wizard'
task_ids = fields.Many2many('todo.task', string='Tasks')
new_deadline = fields.Date('Deadline to Set')
new_user_id = fields.Many2one( 'res.users', string='Responsible to Set')

@api.multi
def do_mass_update(self):
self.ensure_one()
if not (self.new_deadline or self.new_user_id):
raise exceptions.ValidationError('No data to update!')
# else:
_logger.debug('Mass update on Todo Tasks %s', self.task_ids.ids)
if self.new_deadline:
self.task_ids.write({'date_deadline': self.new_deadline})
if self.new_user_id:
self.task_ids.write({'user_id': self.new_user_id.id})
return True
@说明几点:
@ 引入了日志功能,记录的级别如下4级
_logger.debug('A DEBUG message')
_logger.info('An INFO message')
_logger.warning('A WARNING message')
_logger.error('An ERROR message')
# 表单 todo_wizard_view.xml
<openerp>
<data>
<record model="ir.ui.view">
<field name="name">To-do Task Wizard</field>
<field name="model">todo.wizard</field>
<field name="arch" type="xml">
<form>
<div class="oe_right">
<button type="object" name="do_count_tasks"
string="Count"/>
<button type="object" name="do_populate_tasks"
string="Get All"/>
</div>
<field name="task_ids"/>
<group>
<group>
<field name="new_user_id"/>
</group>
<group>
<field name="new_deadline"/>
</group>
</group>
<footer>
<button type="object" name="do_mass_update"
string="Mass Update" class="oe_highlight"
attrs="{'invisible':[('new_deadline','=',False),('new_user_id', '=',False)]}"/>
<button special="cancel" string="Cancel"/>
</footer>
</form>
</field>
</record>
<!-- More button Action -->
<act_window id="todo_app.action_todo_wizard"
name="To-Do Tasks Wizard"
src_model="todo.task" res_model="todo.wizard"
view_mode="form" target="new" multi="True"/>
</data>
</openerp>
@说明:有一个批量更新的逻辑 do_mass_update
# 业务逻辑 todo_wizard_model.py
@api.multi
def do_mass_update(self):
self.ensure_one()
if not (self.new_deadline or self.new_user_id):
raise exceptions.ValidationError('No data to update!')
# else:
_logger.debug('Mass update on Todo Tasks %s', self.task_ids.ids)
if self.new_deadline:
self.task_ids.write({'date_deadline': self.new_deadline})
if self.new_user_id:
self.task_ids.write({'user_id': self.new_user_id.id})
return True
@说明:@api.one 这个是返回一个记录用的 这是主要用 task_ids,所以这里不用
@api.multi 这是是返回一记录列表用
self.ensure_one() 确保是单个,否则报异常
这里有异常处理 :
from openerp import exceptions
raise exceptions.Warning('Warning message')
raise exceptions.ValidationError('Not valid message')
# 自动加载代码变化,这是主要python代码变化,就要手动重启服务,有点麻烦
从而有了 ./odoo.py -d v8dev --auto_reload 自动加载
这个选项可以放到配置文件中 auto_reload = True
有先安装一个依赖,才可以用 pip install pyinotify
# 向导窗口的动作
可以重新打开表单,从而一个表单上的多个按钮可以同时用
@api.multi
def do_reopen_form(self):
self.ensure_one()
return {
'type': 'ir.actions.act_window',
'res_model': self._name, # this model
'res_id': self.id, # the current wizard record
'view_type': 'form',
'view_mode': 'form',
'target': 'new'}
全选:
@api.multi
def do_populate_tasks(self):
self.ensure_one()
Task = self.env['todo.task']
all_tasks = Task.search([])
self.task_ids = all_tasks
# reopen wizard form on same
* 服务端的操作

# 开启命令行交互操作
https://www.odoo.com/apps/modules/8.0/shell/.
把那个shell模块,放到addons中去
$ ./odoo.py shell -d v8dev
指定账套,采用命令交互模式启动
这样就可以测试代码中用到的一些对象,如:
>>> self 得到当前用户对象,这里是超级用户对象
res.users(1,)
>>> self.name
u'Administrator'
>>> self._name
'res.users'
>>> self.env
<openerp.api.Environment object at 0xb3f4f52c>
# 用关系字段
>>> self.company_id
res.company(1,)
>>> self.company_id.name
u'YourCompany'
>>> self.company_id.currency_id
res.currency(1,)
>>> self.company_id.currency_id.name
u'EUR'
#模型中的查询
用self只能得到方法中的字段,但 self.env 可以得到任意其它模型
self.env['res.partner'] 得到合作伙伴对象
运用search() 或 browse() 得到对象的记录
search() 里面是domain表达式,若为空[]则搜索所有的记录
模型中有active字段,默认为True搜索,还有一些参数如下:
order 排序 limit 返回最大记录数 offset 记录数启点位置
search_count()得到记录总数
browse()主要根据记录id 返回记录 多个,采用列表形式。单个时可以直接传入
例子:
>>> self.env['res.partner'].search([('name','like','a')])
res.partner(36, 5, 30, 31, 20, 27, 10, 24, 29, 22, 18)

>>> self.env['res.partner'].browse([5,30])
res.partner(5, 30)
>>> self.env['res.partner'].browse(5)
res.partner(5,)
>>> self.env['res.partner'].browse([5])
res.partner(5,)
#记录上的操作
>>> admin = self.env['res.users'].browse(1)
>>> admin.name='Superuser'
>>> admin.name
@创建一个新记录,但还没有持久化到数据库
>>> Partner = self.env['res.partner']
>>> new = Partner.create({'name':'ACME','is_compnay':True})
>>> print new
res.partner(37,)
@删除记录
>>> rec = Partner.search([('name','=','ACME')])
>>> rec.unlink()
True
@把partner对象全部comment的值改为 'Hello!'
res.partner(37,)
>>> Partner.write({'comment':'Hello!'})
@复制一个记录
>>> demo = self.env.ref('base.user_demo') 得到demo这个用户对角
>>> new = demo.copy({'name': 'Daniel', 'login': 'dr', 'email':''})
>>> self.env.cr.commit()
注:命令效互时操作记录不会记录到数据库中,只有用了 self.env.cr.commit() 后才
会持久化到数据库中
#事务操作和原生sql
self.env.cr 数据库操作句柄
self.env.cr.commit() 事务提交
self.env.savepoit() 事务提交点,回滚时可以来指定回滚到什么位置
self.evn.rollbakc() 事务回滚
原生sql操作 self.env.cr.execute()
self.env.cr.execute("SELECT id, login FROM res_users WHERE login=%s OR id=%s",('demo',1))
self.env.cr.fetchall()
#时间和日期
%Y-%m-%d 和 %Y-%m-%d %H:%M:%S
>>> from openerp import fields
>>> fields.Datetime.now()
'2016-01-25 07:12:34'
>>> fields.Datetime.from_string('2016-12-08 22:23:22')
datetime.datetime(2016, 12, 8, 22, 23, 22)
fields.Date.today() 得到当前的日期是服务器端的
fields.Datetime.now()得到当前的时间是服务器端的
fields.Date.context_today(record,timestamp=None) 从上下文得到当前的日期
fields.Datetime.context_timestamp(record,timestamp) 从上下文得到当前的时间
from_string(value) 字符串转换为日期或时间对象
to_string(value) 日期或时间对象转换为字符串
#关系字段操作
当采用活动记录模式时,用 create() 或 write() 赋关联字段时,不要用对象,要用外键id
不要 self.write({'user_id':self.env.user})
而要改为 self.write({'user_id':self.evn.user.id})
#操作记录集 (集合操作)
rs1 | rs2 求并集 是指两个集合的所有元素构成的集合
rs1 + rs2 求两个集直接连起来,不管重复
rs1 & rs2 求交集 是指两个集合元素相同的部分构成的集合
rs1 - rs2 求差集 是指其中一个集合中除去另一个集合相同元素以后剩余的元素构成的集合
例子说明:
>>> Party=self.env['res.partner']
>>> Party.search([])
res.partner(36, 5, 7, 33, 32, 23, 30, 31, 19, 35, 20, 17, 21, 34, 27, 12, 8, 9, 15, 25, 14, 10, 24, 3, 1, 26, 29, 22, 6, 13, 11, 28, 16, 18)
>>> rs1=Party.browse([1,3,5,7])
>>> rs2=Party.browse([7,32,33])
>>> rs1 | rs2
res.partner(32, 1, 3, 5, 7, 33)
>>> rs1 + rs2
res.partner(1, 3, 5, 7, 7, 32, 33)
>>> rs1 & rs2
res.partner(7,)
>>> rs1 - rs2
res.partner(1, 3, 5)
记录切片(相当于序列切片操作)
>>> rs1
res.partner(1, 3, 5, 7)
>>> rs1[0]
res.partner(1,)
>>> rs1[-1]
res.partner(7,)
>>> rs1[1:]
res.partner(3, 5, 7)

记录集追求记录去除
self.task_ids |= task1 task1在task_ids中没有就增加 <=> self.write([(4, task1.id, False)])
self.task_ids -= task1 task1 在task_ids 减去 <=> self.write([(3, task1.id, False)])
self.task_ids = self.task_ids[:-1] task_ids 删除最后一个记录
<=> self.write([(3, self.task_ids[-1].id, False)])
其它记录集操作
record in recordset 检测一个记录是否在一个记录集中
record not in recordset 检测一个记录是否不在一个记录集中
recordset.ids 记录ID集
recordset.ensure_one() 检测是一个记录
recordset.exists() 若存在返回一个备份
recordset.filtered(func) 过滤记录集
recordset.mapped(func)
recordset.sorted(func) 排序后
len(rs1) 得到记录数
>>> rs1
res.partner(1, 3, 5, 7)
>>> len(rs1)
4
rs1 = rs0.filtered(lambda r:r.name.startswith('H')) 通过name过滤
rs2 = rs0.filtered('is_company') 通过is_compay 为True 来过滤
rs2 = rs0.mapped('name') 得到只有name字段 组成记录集 列表
rs1.sorted(key=lambda r:r.id,reverse=True) 根据id 反向排序
* 执行环境
self.env 具有的属性:
env.cr 数据库操作句柄
env.uid session中的user的id
env.user session中的user对象
env.context session中的上下文,以字典方式组成
环境对象是不能改的只能换,重建
env.sudo(user) 给了用户记录就返回该用户记录,没有,就返回超级用户
env.with_context(dictionary) 换了原有的session
env.with_context(key=value,...) 换指定键的值
env.ref() 要一个 External ID 做为参数
>>> self.env.ref('base.user_root') 这是超级用户的external ID
res.users(1,)

* 客户端效互的模型方法
#
read([fields]) 像search() 但返回来,每一行是一个字典类型
search_read([domain],[fields],offset,limit,order=None) 根据 read()后的结果搜索
load([fields],[data]) 用于ssv数据导入
export_data([fields],raw_data=False) 用于csv数据导出
name_get() 得到(ID,name) 元组的列表 默认是计算 display_name
name_search(name='', args=None, operator='ilike', limit=100) 得到(ID,name) 元组的列表 ,按条件
name_create(name) 创建一个新记录,只用name字段
default_get([fields]) 返回创建新记录时,指定字佰的默认值
fields_get() 得到模型定义的哪些字段
fields_view_get() 得到指定视图类型下可用的字段, 视图类型,有tree ,form,等
#覆盖默认方法
create() 和 write() 这两个方法常扩展
例子如下:
@api.model
def create(self, vals):
# Code before create
# Can use the `vals` dict
new_record = super(TodoTask, self).create(vals)
# Code after create
# Can use the `new` record created
return new_record

@api.multi
def write(self, vals):
# Code before write
# Can use `self`, with the old values
super(TodoTask, self).write(vals)
# Code after write
# Can use `self`, with the new (updated) values
return True
#模型方法修饰器
@api.one 一次得到一条记录
@api.multi 一次得到一个记录集

@api.model 这是类级别静态方法

@api.return(model) 显性返回一个模型
@api.depends(fld1,...)
@api.constrains(fld1,...)
@api.onchange(fld1,...) 可用于警告
#调试
import pdb; pdb.set_trace()

免责声明:文章转载自《(05)odoo数据库和业务操作》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇oracle start with connect by prior 递归查询用法java守护线程(后台线程)下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

odoo使用笔记

1:active字段为False的记录如何显示: odoo中默认,active字段为False的记录上不显示的。但是如果在创建时没有勾选active,之后想要显示它,那就需要吧active修改为True。 然而它现在是不可见的,怎么修改? 通过odoo提供的搜索视图来实现: 自定义筛选——active字段——为假 即可把active为False的记录显示出...

mybatis 中 foreach collection的三种用法

foreach元素的属性主要有 item,index,collection,open,separator,close。 item表示集合中每一个元素进行迭代时的别名, index指 定一个名字,用于表示在迭代过程中,每次迭代到的位置, open表示该语句以什么开始, separator表示在每次进行迭代之间以什么符号作为分隔 符, close表示以什么结...

Odoo学习笔记(一)搭建windows开发环境

前言: 虽然很多人都说学习odoo,最好是linux开发环境,可是我这业余选手有不是只做开发,还有好多活是在windows上做的,我还是做windows开发环境吧。 开始学习Odoo之前,需要具备一些基础知识: 下载git源码、配置python虚拟环境、基本了解数据库服务器的部署和连接、python编程基础知识。 部署Odoo需要掌握Docker,起码知道...

odoo 怎样使代码生效

怎样使 odoo 修改后的代码或文件生效 ? 分以下几类: 修改 python 文件: 必须重启服务,以重写编译生产 *.pyc 文件。 如果是修改函数,不需要升级模块,如果修改模型字段或依赖关系,需要升级模块。 修改 XML 文件: 不需要重启服务, 升级相关模块。 修改CSS 文件: 刷新浏览器重新加载。 修改JS 文件: 刷新浏览器重新加载...

odoo环境搭建

系统: ubuntu 18 版本: odoo 12 社区版 https://www.odoo.com/zh_CN/page/download 1、安装pip sudo apt-get install python3-pip 2、安装虚拟环境 3、 下载odoo源码,解压, 并创建配置文件和启动文件 /opt/odoo12/odoo/odoo/conf to...

vue前端使用axios传参注意事项

axios只支持键值对传参,如果只有一个数据也要封装为键值对,ids为后台接收的参数例如const data = { ids: JSON.stringify(parameter) } 1.如果后台接收的数据类型为数组类型,则,前台组装数据为1,2,2,4,3注意不要加()和[],否则出错2.如果传递集合形式: ids=[1,18,19,20,21,22,2...