class Field(object): """ The field descriptor contains the field definition, and manages accesses and assignments of the corresponding field on records. The following attributes may be provided when instanciating a field: :param string: the label of the field seen by users (string); if not set, the ORM takes the field name in the class (capitalized). :param help: the tooltip of the field seen by users (string) :param readonly: whether the field is readonly (boolean, by default ``False``) :param required: whether the value of the field is required (boolean, by default ``False``) :param index: whether the field is indexed in database (boolean, by default ``False``) :param default: the default value for the field; this is either a static value, or a function taking a recordset and returning a value; use ``default=None`` to discard default values for the field :param states: a dictionary mapping state values to lists of UI attribute-value pairs; possible attributes are: 'readonly', 'required', 'invisible'. Note: Any state-based condition requires the ``state`` field value to be available on the client-side UI. This is typically done by including it in the relevant views, possibly made invisible if not relevant for the end-user. :param groups: comma-separated list of group xml ids (string); this restricts the field access to the users of the given groups only :param bool copy: whether the field value should be copied when the record is duplicated (default: ``True`` for normal fields, ``False`` for ``one2many`` and computed fields, including property fields and related fields) :param string oldname: the previous name of this field, so that ORM can rename it automatically at migration .. _field-computed: .. rubric:: Computed fields One can define a field whose value is computed instead of simply being read from the database. The attributes that are specific to computed fields are given below. To define such a field, simply provide a value for the attribute ``compute``. :param compute: name of a method that computes the field :param inverse: name of a method that inverses the field (optional) :param search: name of a method that implement search on the field (optional) :param store: whether the field is stored in database (boolean, by default ``False`` on computed fields) :param compute_sudo: whether the field should be recomputed as superuser to bypass access rights (boolean, by default ``False``) The methods given for ``compute``, ``inverse`` and ``search`` are model methods. Their signature is shown in the following example:: upper = fields.Char(compute='_compute_upper', inverse='_inverse_upper', search='_search_upper') @api.depends('name') def _compute_upper(self): for rec in self: rec.upper = rec.name.upper() if rec.name else False def _inverse_upper(self): for rec in self: rec.name = rec.upper.lower() if rec.upper else False def _search_upper(self, operator, value): if operator == 'like': operator = 'ilike' return [('name', operator, value)] The compute method has to assign the field on all records of the invoked recordset. The decorator :meth:`odoo.api.depends` must be applied on the compute method to specify the field dependencies; those dependencies are used to determine when to recompute the field; recomputation is automatic and guarantees cache/database consistency. Note that the same method can be used for several fields, you simply have to assign all the given fields in the method; the method will be invoked once for all those fields. By default, a computed field is not stored to the database, and is computed on-the-fly. Adding the attribute ``store=True`` will store the field's values in the database. The advantage of a stored field is that searching on that field is done by the database itself. The disadvantage is that it requires database updates when the field must be recomputed. The inverse method, as its name says, does the inverse of the compute method: the invoked records have a value for the field, and you must apply the necessary changes on the field dependencies such that the computation gives the expected value. Note that a computed field without an inverse method is readonly by default. The search method is invoked when processing domains before doing an actual search on the model. It must return a domain equivalent to the condition: ``field operator value``. .. _field-related: .. rubric:: Related fields The value of a related field is given by following a sequence of relational fields and reading a field on the reached model. The complete sequence of fields to traverse is specified by the attribute :param related: sequence of field names Some field attributes are automatically copied from the source field if they are not redefined: ``string``, ``help``, ``readonly``, ``required`` (only if all fields in the sequence are required), ``groups``, ``digits``, ``size``, ``translate``, ``sanitize``, ``selection``, ``comodel_name``, ``domain``, ``context``. All semantic-free attributes are copied from the source field. By default, the values of related fields are not stored to the database. Add the attribute ``store=True`` to make it stored, just like computed fields. Related fields are automatically recomputed when their dependencies are modified. .. _field-company-dependent: .. rubric:: Company-dependent fields Formerly known as 'property' fields, the value of those fields depends on the company. In other words, users that belong to different companies may see different values for the field on a given record. :param company_dependent: whether the field is company-dependent (boolean) .. _field-sparse: .. rubric:: Sparse fields Sparse fields have a very small probability of being not null. Therefore many such fields can be serialized compactly into a common location, the latter being a so-called "serialized" field. :param sparse: the name of the field where the value of this field must be stored. .. _field-incremental-definition: .. rubric:: Incremental definition A field is defined as class attribute on a model class. If the model is extended (see :class:`~odoo.models.Model`), one can also extend the field definition by redefining a field with the same name and same type on the subclass. In that case, the attributes of the field are taken from the parent class and overridden by the ones given in subclasses. For instance, the second class below only adds a tooltip on the field ``state``:: class First(models.Model): _name = 'foo' state = fields.Selection([...], required=True) class Second(models.Model): _inherit = 'foo' state = fields.Selection(help="Blah blah blah") """
在认识odoo ORM框架前,先介绍一下odoo中模块目录结构。
python
data
:存放模块预制数据i18n
:存放国际化文件models
:存放模型等py代码security
:存放权限文件views
:存放视图文件__manifest__.py
:该文件用于声明该模块,并指定一些模块元数据。(odoo8时该文件为__openerp__.py
。)
git
# -*- coding: utf-8 -*- { # name:模块名称 'name': " test", # description:模块描述 'description': """ 自定义模块 """, # author:模块做者(XXX公司或张三) 'author': "Hu", # website:做者或公司网址 'website': "http://weibo.com/hcw1202", # category:模块分类 'category': "test", # version:模块版本 'version': "版本", # depends:所依赖其余模块 'depends': ["base","stock","sale"], # 模块安装时加载 'data': [ 'security/权限文件.csv', 'data/预制数据.xml', 'views/视图文件.xml', ], # 建立数据库时勾选Load demonstration data后安装该模块加载演示数据 'demo': [ 'data/演示数据.xml', ], }
在/models下添加test.py
文件web
# -*- coding: utf-8 -*- from odoo import models, api, fields, _ class Test(models.Model): # 模型惟一标识(对应数据表为product_manage_product) _name = 'product_manage.product' # 数据显示名称,如设置则返回其指定的字段值 _rec_name = 'test_field' # 字段 test_field = fields.Char(string="字段名称")
model属性详解:_name
:模型惟一标识,类非继承父类时必须指定。_rec_name
:数据显示名称,如设置则返回其指定的字段值,不设置默认显示字段为name的字段值,如无name字段则显示"模块名,id";详见BaseModel.name_get
方法。_log_access
:是否自动增长日志字段(create_uid
, create_date
,write_uid
, write_date
)。默认为True。_auto
:是否建立数据库对象。默认为True,详见BaseModel._auto_init方法。_table
:数据库对象名称。缺省时数据库对象名称与_name指定值相同(.
替换为下划线)。_sequence
:数据库id字段的序列。默认自动建立序列。_order
:数据显示排序。所指定值为模型字段,按指定字段和方式排序结果集。sql
例:_order = "create_date desc":根据建立时间降序排列。可指定多个字段。
不指定desc默认升序排列;不指定_order默认id升序排列。数据库
_constraints
:自定义约束条件。模型建立/编辑数据时触发,约束未经过弹出错误提示,拒绝建立/编辑。api
格式:
_constraints = [(method, 'error message', [field1, ...]), ...]
method
:检查方法。返回True|False
error message
:不符合检查条件时(method返回False)弹出的错误信息
[field1, ...]
:字段名列表,这些字段的值会出如今error message中。app
_sql_constraints
:数据库约束。框架
例:
_sql_constraints = [ ('number_uniq', 'unique(number, code)', 'error message') ]
会在数据库添加约束:
CONSTRAINT number_uniq UNIQUE(number, code)
dom
_inherit
:单一继承。值为所继承父类_name标识。如子类不定义_name属性,则在父类中增长该子类下的字段或方法,不建立新对象;如子类定义_name属性,则建立新对象,新对象拥有父类全部的字段或方法,父类不受影响。ide
格式:
_inherit = '父类 _name'
_inherits
:多重继承。子类经过关联字段与父类关联,子类不拥有父类的字段或方法,可是能够直接操做父类的字段或方法。
格式:
_inherits = {'父类 _name': '关联字段'}
Char
:字符型,使用size参数定义字符串长度。Text
:文本型,无长度限制。Boolean
:布尔型(True,False)Interger
:整型Float
:浮点型,使用digits参数定义整数部分和小数部分位数。如digits=(10,6)
Datetime
:日期时间型Date
:日期型Binary
:二进制型selection
:下拉框字段。
例:
state = fields.Selection([('draft', 'Draft'),('confirm', 'Confirmed'),('cancel', 'Cancelled')], string='Status')
Html
:可设置字体格式、样式,可添加图片、连接等内容。效果以下:
截于odoo自带项目管理模块
One2many
:一对多关系。
定义:
otm = fields.One2many("关联对象 _name", "关联字段",string="字段显示名",...
)
例:analytic_line_ids = fields.One2many('account.analytic.line', 'move_id', string='Analytic lines')"
Many2one
定义:
mto = fields.Many2one("关联对象 _name", string="字段显示名",...
)
可选参数:ondelete,可选值为‘cascade’和‘null’,缺省为null。表示one端删除时many端是否级联删除。
Many2many
定义:
mtm = fields.Many2many("关联对象 _name", "关联表/中间表","关联字段1","关联字段2",string="字段显示名"
,...)
其中,关联字段、关联表/中间表可不填,中间表缺省为:表1_表2_rel
例:partner_id= fields.Many2many("res.partner", string="字段显示名",...)"
readonly
:是否只读,缺省值False。required
:是否必填,缺省值Falsse。string
:字段显示名,任意字符串。default
:字段默认值domain
:域条件,缺省值[]。在关系型字段中,domain用于过滤关联表中数据。help
:字段描述,鼠标滑过期提示。store
:是否存储于数据库。结合compute和related使用。
例:
sale_order = fields.One2many("sale.order", "contract_id",string="销售订单", domain=[('state','=','sale')])
compute
:字段值由函数计算,该字段可不储存于数据库。
例:
amount = fields.Float(string="金额总计", compute=‘_compute_amount’,store=True)
_compute_amount
为计算函数。
related
:字段值引用关联表中某字段。
如下代码表示:
company_id
引用hr.payroll.advice
中company_id
advice_id = fields.Many2one('hr.payroll.advice', string='Bank Advice') company_id = fields.Many2one('res.company', related='advice_id.company_id', string='Company', store=True)
以上便是Model的主要属性,下一节会介绍Model中经常使用的方法