以一个例子开头
* 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 id="To-do Task Wizard" 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数据库和业务操作的更多相关文章

  1. MySQL数据库的常见操作(七)

    MySQL数据库的常见操作 1.创建数据库 2.创建重名的数据库以及如何查看警告信息 3.设置数据库的编码方式(默认为utf8) 4.修改和查看数据库的编码方式 5.删除数据库 6.6.删除已经删除了 ...

  2. 怎样加快master数据库的写操作?分表原则!将表水平划分!或者添加写数据库的集群

    1.怎样加快master数据库的写操作?分表原则!将表水平划分!减少表的锁定时间!!! 或者或者添加写数据库的集群!!!或者添加写数据库的集群!!! 2.既然分表了,就一定要注意分表的规则!要在代码层 ...

  3. Odoo(OpenERP)开发实践:通过XML-RPC接口访问Odoo数据库

    Odoo(OpenERP)服务器支持通过XML-RPC接口访问.操作数据库,基于此可实现与其他系统的交互与集成. 本文是使用Java通过XMLRPC接口操作Odoo数据库的简单示例.本例引用的jar包 ...

  4. Odoo(OpenERP)开发实践:通过XML-RPC接口訪问Odoo数据库

    Odoo(OpenERP)server支持通过XML-RPC接口訪问.操作数据库,基于此可实现与其它系统的交互与集成. 本文是使用Java通过XMLRPC接口操作Odoo数据库的简单演示样例.本例引用 ...

  5. SQL Server性能调优——报表数据库与业务数据库分离

    前段时间把公司的主数据库切了,分成业务库和报表库,业务库向报表库进行实时的Replication.这个项目的上线提升了系统的性能和可维护性,现在把设计时的考量和所做的工作重新回顾一下,作为备忘. 项目 ...

  6. 【Docker】 .Net Core 3.1 webapi 集成EF Code First,使用MySql进行业务操作 、配置swagger (三)

    系列目录: [Docker] CentOS7 安装 Docker 及其使用方法 ( 一 ) [Docker] 使用Docker 在阿里云 Centos7 部署 MySQL 和 Redis (二) [D ...

  7. python操作mysql数据库的相关操作实例

    python操作mysql数据库的相关操作实例 # -*- coding: utf-8 -*- #python operate mysql database import MySQLdb #数据库名称 ...

  8. MySQL数据库定义与操作语言

    文章为作者原创,未经许可,禁止转载.    -Sun Yat-sen University 冯兴伟 实验1.1 数据库定义 (1)实验目的 理解和掌握数据库DDL语言,能够熟练地使用SQL DDL语句 ...

  9. 在php中需要用到的mysql数据库的简单操作

    1.数据库连接 1.1用windows命令行链接数据库服务器 几个DOS命令 在DOS环境下命令后面没有分号,在MySQL环境下,命令后面有分号 进入盘符: 语法:盘符: 进入盘符下的某个文件夹 语法 ...

随机推荐

  1. linux终端下为什么用命令打开软件后,要关闭软件才能继续下一条命令?

    用终端打开chromium浏览器(命令:chromium-browser)的时候发现打开浏览器之后无法继续在终端输入命令,只能关闭浏览器或者在终端按下Ctrl+c,此时系统将退出浏览器并可以继续在终端 ...

  2. eclipse启动报错eclipse failed to create the java virutal machine

    早上一来,我的eclipse就无法启动了,错误就是这句话: eclipse failed to create the java virutal machine 直译就是eclipse无法创建JAVA虚 ...

  3. Know How To Use Check Box Mapping Of Other Values Property In Oracle Forms

    Check Box Mapping of Other Values specifies how any fetched or assigned value that is not one of the ...

  4. 头文件为什么要加#ifndef #define #endif

    #ifndef 在头文件中的作用 在一个大的软件工程里面,可能会有多个文件同时包含一个头文件,当这些文件编译链接成一个可执行文件时 ,就会出现大量“重定义”的错误.在头文件中实用#ifndef #de ...

  5. sencha touch之store

    store相当于数据库的表,是模型实例的集合.(是不是可以看成结构体数组) 可以对模型实例进行新建.更新.读取.删除.排序和过滤等操作. 创建store 由于store是表,必须要有模型或者定义字段, ...

  6. 自定义类型转换器converter

    作用:目前将日期转换成string,将string转换成我想要的类型   0509课件里讲 一.数据类型转换在web应用程序中,数据存在两个方向上的转换:1.当提交表单时  表单数据以字符串的形式提交 ...

  7. [SAP ABAP开发技术总结]ABAP程序之间数据共享与传递

    声明:原创作品,转载时请注明文章来自SAP师太技术博客( 博/客/园www.cnblogs.com):www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将 ...

  8. JavaScript经典代码【二】【javascript判断用户点了鼠标左键还是右键】

    IE 下 onMouseDown 事件有个 events.button 可以返回一个数值,根据数值判断取得用户按了那个鼠标键 events.button==0 默认.没有按任何按钮. events.b ...

  9. CUBRID学习笔记 45 REPLACE DELETE MERGE 教程

    c#,net,cubrid,教程,学习,笔记欢迎转载 ,转载时请保留作者信息.本文版权归本人所有,如有任何问题,请与我联系wang2650@sohu.com . 过错 ------ 官方文档是英文的, ...

  10. input与lable水平对齐

    CSSinput,label { vertical-align:middle;}  html 格式 <label><input/></label> <labe ...