创建模型: 
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 

查看系统已注册的模型
技术->数据结构->模型
 

* 基本字段类型:
例子:
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 字符串
# Text 文本
# Selection 下接选择列表
# Html html文本
# Integer 整型
# Float 浮点数
# Date 日期
# Datetime 时间
# Boolean 布尔值
# Bninary 二进制

* 普通字段属性
# 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')

# 引用字段动态关系 
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

# 搜索和写入
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!')