(03)odoo模型/记录集/公用操作

*模型
  模型是业务对象的呈现

* 创建模型: 
  class Stage(models.Model):
    _name = ‘todo.task.stage‘ 
    _order = ‘sequence,name‘
    _rec_name = ‘name‘
    _table = ‘todo_task_stage‘
   
    # _name 模型的标识符,用于引用
    # _order 用于browsed时的记录的排序
    # _rec_name 覆盖默认的name字段
    # _table 映射到数据库的表名,可自定义,默认是模型标识符把"."换成"_" 连启来   
   
    得到模型
     self.envl[‘todo.task.stage‘]  或 self.evn.get(‘todo.task.stage‘)
    
    Transient 和 Abstract
   
    查看系统已注册的模型
     技术->数据结构->模型   
    
* 三种常用继承 (在model中操作)
    _inherit 没重定义_name  这样数据库不会新建对象表,用被继承的表
    _inherit 重定义_name 这样数据库会创建新的对象表存储
    _inherits 是复合继承,有模型对象,有字段对象
   
    示例:
   
    class MyModelExtended(Model):
     _inherit = ‘a.model‘                       # direct heritage
     _inherit = [‘a.model, ‘a.other.model‘]     # direct heritage
     _inherits = {‘a.model‘: ‘field_name‘}      # polymorphic heritage

* 基本字段类型:
    例子:
    name = fields.Char(‘Name‘,40,translate=True)
    desc = fields.Text(‘Description‘)
    state = fields.Selection( [(‘draft‘,‘New‘), (‘open‘,‘Started‘),(‘done‘,‘Closed‘)],‘State‘)
    docs = fields.Html(‘Documentation‘)
    sequence = fields.Integer(‘Sequence‘)
    perc_complete = fields.Float(‘% Complete‘,(3,2))
    date_effective = fields.Date(‘Effective Date‘)
    date_changed = fields.Datetime(‘Last Changed‘)
    fold = fields.Boolean(‘Folded‘)
    image = fields.Binary(‘Image‘)

# Char 字符串
        size:字符串长度
        translate 字符串可翻译
       
   # Text 文本
        translate 字符串可翻译
       
   # Selection 下接选择列表
        下接选择列表
        例子:
            aselection = fields.Selection([(‘a‘, ‘A‘)])
            aselection = fields.Selection(selection=[(‘a‘, ‘A‘)])
            aselection = fields.Selection(selection=‘a_function_name‘)
           
            class SomeModel(models.Model):
                _inherits = ‘some.model‘
                type = fields.Selection(selection_add=[(‘b‘, ‘B‘), (‘c‘, ‘C‘)])    #增加选项               
       
   # Html html文本
        translate 字符串可翻译
       
   # Integer 整型
   # Float   浮点数
        digits 设定 整数部分的长度,和小数部分的精度位 afloat = fields.Float(digits=(32, 32))
   # Date  日期
        context_tody 得到今天的日期
        today 得到系统的日期
        from_string 从字符串转转成日期对象
        to_string 从日期对象转字符串
        例子:
            >>> from openerp import fields

>>> adate = fields.Date()
            >>> fields.Date.today()
            ‘2014-06-15‘
            >>> fields.Date.context_today(self)
            ‘2014-06-15‘
            >>> fields.Date.context_today(self, timestamp=datetime.datetime.now())
            ‘2014-06-15‘
            >>> fields.Date.from_string(fields.Date.today())
            datetime.datetime(2014, 6, 15, 19, 32, 17)
            >>> fields.Date.to_string(datetime.datetime.today())
            ‘2014-06-15‘   
           
   # Datetime 时间
        context_timestamp 得到今天的时间
        now 得到系统的时间
        from_string 从字符串转转成日期对象
        to_string 从日期对象转字符串   
        例子:
            >>> fields.Datetime.context_timestamp(self, timestamp=datetime.datetime.now())
            datetime.datetime(2014, 6, 15, 21, 26, 1, 248354, tzinfo=<DstTzInfo ‘Europe/Brussels‘ CEST+2:00:00 DST>)
            >>> fields.Datetime.now()
            ‘2014-06-15 19:26:13‘
            >>> fields.Datetime.from_string(fields.Datetime.now())
            datetime.datetime(2014, 6, 15, 19, 32, 17)
            >>> fields.Datetime.to_string(datetime.datetime.now())
            ‘2014-06-15 19:26:13‘       
       
   # Boolean 布尔值
   # Bninary 二进制
        储存文件采用 base64编码

* 普通字段属性
   # string  是字段的标题,
   # default 设置字段的默认值
   # size  只用于Char 设置可最大接收字符数
   # translate 用于Text Char Html 标识字段标题或内容可翻译
   # help 用于悬挂提示
   # readonly=True 设置字段只读
   # required=True 设置字段不能为空
   # index = True 设置字段创建索引
   # copy=False 设置字段不能被复制
   # groups 设置权限组访问可见
   # states 设置字段状态,接收字典 如:states={‘done‘:[(‘readonly‘,True)]}
   # deprecated=True 当用这个字段,日志会记录警告,主要是版本升级一些过渡字段
   # oldname=‘field‘ 当一个字段在新版本重命名了,指定老的字段,老的字段的数据会自动拷贝到新的字段中

*保留字段名字
   # id 数据库自动生成做为主键
   # create_uid 创建记录时的用户
   # create_date 创建记录时的日期和时间
   # write_uid 修改记录时的最后用户
   # write_date 修改记录时最后日期和时间

*内置专用字段名
   # name  (Char)  记录的默认名,但可以用 _rec_name 去覆盖  
   # active (Boolean) 标识记录的有效性 常用于domain  domain是元组表达式
   # sequence (Integer) 用在列表视图记录排序
   # state (Selection) 显示记录的生命周期
   # parent_id, parent_left, parent_right  用于记录的上下级

* 模型的关系
  例子:
  class TodoTask(models.Model):
    _inherit = ‘todo.task‘
    stage_id = fields.Many2one(‘todo.task.stage‘,‘Stage‘)
    tage_ids =fields.Many2many(‘todo.task.tag‘,string=‘Tages‘)

model 和 string 所有关系都接受属性,
   # 多对一 Many2one
      接受属性:
              @ ondelete 默认值为set null 表示关联记录删除 本字段设为空
                         restrict 接连删除对应关联的记录
              @ context  domain 是上下文,功能强大
              @ auto_join=True 允许用sql 语句来关联
   # 一对多 One2Many
     接受的属性 和 Many2one 一样
     可以很简单地从one得到many方的对应的所有记录
              class Stage(models.Model):
                 _name = ‘todo.task.stage‘
                 Stage class relation with Tasks:
                 tasks = fields.One2many(
                   ‘todo.task‘, # related model
                   ‘stage_id‘, # field for "this" on related model
                   ‘Tasks in this stage‘)

# 多对多 Many2many
             tag_ids = fields.Many2many(
             ‘todo.task.tag‘, # related model
             ‘todo_task_tag_rel‘, # relation table name
             ‘task_id‘, # field for "this" record
             ‘tag_id‘, # field for "other" record
             string=‘Tasks‘)

也可以用长表单键表示
             tag_ids = fields.Many2many(
             comodel_name=‘todo.task.tag‘, # related model
             relation=‘todo_task_tag_rel‘, # relation table name
             column1=‘task_id‘, # field for "this" record
             column2=‘tag_id‘, # field for "other" record
             string=‘Tasks‘)

# 父子分层
     可以用Many2one 表示子到父, 用One2many 表示父到子

class Tags(models.Model):
                _name = ‘todo.task.tag‘
                _parent_store = True
                # _parent_name = ‘parent_id‘
                name = fields.Char(‘Name‘)
                parent_id = fields.Many2one(
                  ‘todo.task.tag‘, ‘Parent Tag‘, ondelete=‘restrict‘)
                parent_left = fields.Integer(‘Parent Left‘, index=True)
                parent_right = fields.Integer(‘Parent Right‘, index=True)
     为了方便还会加一个字段
                child_ids = fields.One2many(‘todo.task.tag‘, ‘parent_id‘, ‘Child Tags‘)
   # One2Many 和 Many2many 的 eval 赋值
     <field name=”tag_ids”
        eval=”[(6,0,
        [ref(’vehicle_tag_leasing’),
        ref(’fleet.vehicle_tag_compact’),
        ref(’fleet.vehicle_tag_senior’)]
        )]” />
       
      (0,_ ,{’field’: value}) 这将创建一个新的记录并连接它
      (1,id,{’field’: value}): 这是更新一个已经连接了的记录的值
      (2,id,_) 这是删除或取消连接某个已经连接了的记录
      (3,id,_) 这是取消连接但不删除一个已经连接了的记录
      (4,id,_) 连接一个已经存在的记录
      (5,_,_) 取消连接但不删除所有已经连接了的记录
      (6,_,[ids]) 用给出的列表替换掉已经连接了的记录
      这里的下划线一般是0或False

# 引用字段动态关系 
       Refers to

class TodoTask(models.Model):
                 refers_to = fields.Reference(
                   [(‘res.user‘, ‘User‘), (‘res.partner‘, ‘Partner‘)],
                   ‘Refers to‘)

可用保用任何注册模型
    
     from openerp.addons.base.res import res_request
     def referencable_models(self):
         return res_request.referencable_models(
           self, self.env.cr, self.env.uid, context=self.env.context)
          
    class TodoTask(models.Model):
          refers_to = fields.Reference(
             referencable_models, ‘Refers to‘)    
    这样就不会只局限在用户和合作伙伴两个模型了            
          
* 字段操作
   # 计算
     class TodoTask(models.Model):
       stage_fold = fields.Boolean(
         ‘Stage Folded?‘,
         compute=‘_compute_stage_fold‘)
        
       @api.one
       @api.depends(‘stage_id.fold‘)
       def _compute_stage_fold(self):
         self.stage_fold = self.stage_id.fold
        
   # 关联字段
      participant_nick = fields.Char(string=‘Nick name‘,
                               related=‘partner_id.name‘)
      合作伙伴名字改,该对象的昵称跟着变化
     
        
   # 搜索和写入
     class TodoTask(models.Model):
       stage_fold = fields.Boolean(
         ‘Stage Folded?‘,
         compute=‘_compute_stage_fold‘,
         # store=False) # the default
         search=‘_search_stage_fold‘,
         inverse=‘_write_stage_fold‘)
        
       @api.one
       @api.depends(‘stage_id.fold‘)
       def _compute_stage_fold(self):
         self.stage_fold = self.stage_id.fold

def _search_stage_fold(self, operator, value):
         return [(‘stage_id.fold‘, operator, value)]

def _write_stage_fold(self):
         self.stage_id.fold = self.stage_fold   
   # 为了搜索加字段
       stage_state = fields.Selection(
       related=‘stage_id.state‘,
       string=‘Stage State‘)  
      
   # 模型约束(SQL 和 Python)
     #一个用户在一时间只有一个活动的任务,加复合主键一样
     class TodoTask(models.Model):
       _sql_constraints = [
         (‘todo_task_name_uniq‘,
         UNIQUE (name, user_id, active)‘,
         ‘Task title must be unique!‘)]
     
     #检查名称少于5个字符     
     class TodoTask(models.Model):
       @api.one
       @api.constrains(‘name‘)
       def _check_name_size(self):
          if len(self.name) < 5:
            raise ValidationError(‘Must have 5 chars!‘)
           
* 记录集
   一个模型的实例同时也是一个记录集的实例
   一个记录集是同一个模型的一组记录
   class AModel(Model):
    # ...
    def a_fun(self):
        self.do_something() # self 在这里就是一个记录集,会包含很多记录
        record_set = self
        record_set.do_something()

def do_something(self):
        for record in self:
           print record
     如果用了@api.one 来修饰,self 就会当前一条记录,不是记录集了

*记录集支持的操作   
    rs1 | rs2  求并集 是指两个集合的所有元素构成的集合
    rs1 +    rs2   求两个集直接连起来,不管重复
    rs1 & rs2   求交集 是指两个集合元素相同的部分构成的集合
    rs1 - rs2   求差集 是指其中一个集合中除去另一个集合相同元素以后剩余的元素构成的集合
    rs1.copy()  浅拷贝
   
    #其它记录集操作
    record in recordset   检测一个记录是否在一个记录集中
    record not in recordset      检测一个记录是否不在一个记录集中

recordset.ids 记录ID集
    recordset.ensure_one() 检测是一个记录
    recordset.exists() 若存在返回一个备份
    recordset.filtered(func) 过滤记录集
    recordset.mapped(func)
    recordset.sorted(func) 排序后
   
        # filtered()
         recset.filtered(lambda record: record.company_id == user.company_id)
         recset.filtered("product_id.can_be_sold")
    
        # sorted()  
          recset.sorted(key=lambda r: r.name)
         
         from operator import attrgetter
         recset.sorted(key=attrgetter(‘partner_id‘, ‘name‘))
       
        # mapped()
         recset.mapped(lambda record: record.price_unit - record.cost_price)

# 从记录集抽出 name 这一列再组成记录集
         recset.mapped(‘name‘)

# 返回合作伙伴记录集
          recset.mapped(‘invoice_id.partner_id‘)

* 特殊记录集ids属性

* 一些记录的操作
     # 得到记录的显示名称
        name_get() 方法   对应的字段是 display_name
       
* 环境操作
   # self.env 得到环境
        def afun(self):
         self.env
         # or
         model.env
        
    #修改环境
      self.env[‘res.partner‘].with_context(tz=x).create(vals)
      不能用这个函数来修改当前的环境
     
    # 切换用户
        self.sudo(user.id)
        self.sudo()   # 会切换到超级用户
        # or
        self.env[‘res.partner‘].sudo().create(vals)
       
    # 得到当前用户
        self.env.user
       
    # 得到xml的记录
        self.evn.ref(‘base.main_company‘)
       
    # 清理环境缓存
        self.env.invalidate_all()
     
* 公用操作
    # 搜索
        >>> self.search([(‘is_company‘, ‘=‘, True)])
        res.partner(7, 6, 18, 12, 14, 17, 19, 8,...)
        >>> self.search([(‘is_company‘, ‘=‘, True)])[0].name
        ‘Camptocamp‘
       
    # 搜索读到字典中
        >>> self.search_read([], [‘name‘])
        [{‘id‘: 3, ‘name‘: u‘Administrator‘},
         {‘id‘: 7, ‘name‘: u‘Agrolait‘},
         {‘id‘: 43, ‘name‘: u‘Michel Fletcher‘},
         ...]   
    # 从id搜索
        >>> self.browse([1, 2, 3])
        res.partner(1, 2, 3)
       
    # 活动记录写
        @api.one
        def any_write(self):
          self.x = 1
          self.name = ‘a‘       
         
    # 记录写
        @api.one
        ...
        self.write({‘key‘: value })
        # or
        record.write({‘key‘: value})   
       
    # 记录集写
        @api.multi
        ...
        self.write({‘key‘: value })
        # It will write on all record.
        self.line_ids.write({‘key‘: value })   
       
    # Many2many One2Many的行为
        self.line_ids.create({‘name‘: ‘Tho‘})   #
        self.line_ids.create({‘name‘: ‘Tho‘, ‘order_id‘: self.id})  #
        self.line_ids.write({‘name‘: ‘Tho‘})    # 保存所有的相关记录
       
    # 记录拷贝
        >>> @api.one
        >>> ...
        >>>     self.copy()
        broken
       
    # 记录集拷贝
        >>> @api.multi
        >>> ...
        >>>     self.copy()
        broken
       
    # 创建记录
        self.create({‘name‘: ‘New name‘})
       
* 使用数据库操作句柄
    def my_fun(self):
    cursor = self._cr
    # or
    self.env.cr
   
* 保用线程
    with Environment.manage():  # class function
        env = Environment(cr, uid, context)

时间: 2024-08-24 02:30:17

(03)odoo模型/记录集/公用操作的相关文章

(03)odoo 模型操作

* 创建模型: class Stage(models.Model): _name = 'todo.task.stage' _order = 'sequence,name' _rec_name = 'name' _table = 'todo_task_stage' # _name 模型的标识符,用于引用 # _order 用于browsed时的记录的排序 # _rec_name 覆盖默认的name字段 # _table 映射到数据库的表名,可自定义,默认是模型标识符把"."换成"

Mysql数据库连接、查询、记录集操作代码

Mysql数据库链接代码 function dbConnect($hostname,$username,$pass,$db_name,$pconnect =0) { $func=empty($pconnect) ? 'mysql_connect':'mysql_pconnect'; if(!$connect){ [email protected]$func($hostname,$username,$pass) or die("<font size='2'>Mysql_Error :

DB 查询分析器 6.03 如何灵活、快捷地操作国产达梦数据库

DB 查询分析器 6.03 如何灵活.快捷地操作国产达梦数据库 马根峰 (广东联合电子服务股份有限公司, 广州 510300) 摘要       本文详细地介绍了"万能数据库查询分析器",中文版本<DB 查询分析器>.英文版本<DB Query Analyzer>6.03如何灵活.快捷地操作国产达梦数据库.除了创建基于不同数据库产品的ODBC数据源有所不同外,用"万能数据库查询分析器"操作任何数据库.EXCEL.TXT/CSV文件的方法跟本文

存储过程不返回记录集导致ADO程序出错

HRESULT _hr = get_adoEOF(&_result); IsEOF()函数如下:其中ADOCG::_RecordsetPtr m_pRecordset; BOOL IsEOF()       {return m_pRecordset->adoEOF == VARIANT_TRUE;}; m_pRecordset->adoEOF 将执行下面的函数(见msado15.tli) 1    inline VARIANT_BOOL Recordset15::GetadoEOF (

分布式缓存技术redis学习系列(四)——redis高级应用(集群搭建、集群分区原理、集群操作)

本文是redis学习系列的第四篇,前面我们学习了redis的数据结构和一些高级特性,点击下面链接可回看 <详细讲解redis数据结构(内存模型)以及常用命令> <redis高级应用(主从.事务与锁.持久化)> 本文我们继续学习redis的高级特性--集群.本文主要内容包括集群搭建.集群分区原理和集群操作的学习. Redis集群简介 Redis 集群是3.0之后才引入的,在3.0之前,使用哨兵(sentinel)机制(本文将不做介绍,大家可另行查阅)来监控各个节点之间的状态.Redi

SQL Server里如何随机记录集

今天的文章,我想给你简单介绍下SQL Server里如何随机记录集. 1 SELECT * FROM Person.Person 2 ORDER BY NEWID() 3 GO 这会引入新的UNIQUEIDENTIFIER数据类型列,SQL Server会在那列上进行物理排序操作. 但是在记录集里列本身没有返回,因为ORDER BY子句在查询SELECT部分逻辑后发生,因此也不会改变记录集. 在SQL Server里,简单但很强大的方法用来随机化你的记录集. 感谢关注!

关于ADO记录集GetRecordCount()返回记录条数-1的问题

ADO方式操作数据库我们通常使用GetRecordCount函数来快速判断一个打开的记录集里面总共有多少条记录,但在使用中有时却发现有时可能查不到任何的数据,跟踪发现GetRecordCount()返回值变成了-1,而且记录集里也有记录存在. 一般情况下当ADO不能确定记录条数,或者连接提供者.游标类型都不支持RecordCount的时候,RecordCount属性都将返回-1. 最常用的两个游标类型是: adUseClient 使用由本地游标库提供的客户端游标.本地游标引擎通常允许使用的许多功

ODBC更新记录集提示”记录集为只读“

创建的ODBC应用程序默认的记录集不具有只读属性,但是再更新记录表时会提示"记录集为只读",这是为什么呢? 今天看书找到了答案: 因为MFC中的数据库类不支持需要连接两个或者多个表的记录集更新,如果选择数据源的时候选择多个表,则记录集的更新操作是禁止的,因为那样使记录集自动具有只读属性,此时该数据库只支持对连接多个表的记录集进行只读访问,而不支持对其进行更新操作.

03_Kafka集群操作

1.集群配置思路 1)每台节点上要启动一个broker进程,因此要配置每台的server.properties broker id, log.dirs, zookeeper.connect 2) 每台broker都要连接zookeeper将状态写入,因此要配置每台的zookeeper.properties dataDir, zookeeper集群snapshot数据的存放地址,和zookeeper集群的配置保持一致 3)zookeeper.properties 可以在一台节点上配置,并分发给其他