Fields
1.Simple fields
There are two broad categories of fields: "simple" fields which are atomic values stored directly in the model's table and "relational" fields linking records (of the same model or of different models).
Example of simple fields are Boolean, Date, Char.
2.Reserved fields
Odoo creates a few fields in all models. These fields are managed by the system and shouldn't be written to. They can be read if useful or necessary:
id (Id)
the unique identifier for a record in its model
create_date (Datetime)
creation date of the record
create_uid (Many2one)
user who created the record
write_date (Datetime)
last modification date of the record
write_uid (Many2one)
user who last modified the record
3.Special fields
By default, Odoo also requires a name field on all models for various display and search behaviors. The field used for these purposes can be overridden by setting
_rec_name.
4.Relational fields
Relational fields link records, either of the same model (hierarchies) or between different models.
Relational field types are:
Many2one(other_model, ondelete='set null')
One2many(other_model, related_field)
A virtual relationship, inverse of a Many2one. A One2many behaves as a container of records, accessing it results in a (possibly empty) set of records:
Note:Because a One2many is a virtual relationship, there must be a Many2one field in the other_model, and its name must be related_field
Many2many(other_model)
Bidirectional multiple relationship, any record on one side can be related to any number of records on the other side. Behaves as a container of records, accessing it also results in a possibly empty set of records:
Field types
1.Boolean
:Checkbox
2.Char
:TextBox
3.Text
:TextArea
4.HTML
5.Integer
6.Float
7.Date
:Calendar
8.DateTime
9.Binary
:Image
10.Selection
:DropDown
11.Reference
12.Many2one
13.One2many
14.Many2many
from openerp import models, field
class AModel(models.Model):
_name = 'a_name'
name = fields.Char(
string="Name", # Optional label of the field
compute="_compute_name_custom", # Transform the fields in computed store=True, # If computed it will store the result
select=True, # Force index on field
readonly=True, # Field will be readonly in views
inverse="_write_name" # On update trigger
required=True, # Mandatory field
translate=True, # Translation enable
help='blabla', # Help tooltip text
company_dependent=True, # Transform columns to ir.property
search='_search_function' # Custom search function mainly used with compute
)
# The string key is not mandatory
# by default it wil use the property name Capitalized
name = fields.Char() # Valid definition
Field types
1.Boolean
Store True/False (Checkbox)
Boolean type field:
abool = fields.Boolean()
2.Char
Store string with variable len.:
achar = fields.Char()
Specific options:
size: data will be trimmed to specified size
translate: field can be translated
3.Text
Used to store long text.:
atext = fields.Text()
Specific options:
translate: field can be translated
4.HTML
Used to store HTML, provides an HTML widget.:
anhtml = fields.Html()
Specific options:
translate: field can be translated
5.Integer
Store integer value. No NULL value support. If value is not set it returns 0:
anint = fields.Integer()
6.Float
Store float value. No NULL value support. If value is not set it returns 0.0 If digits option is set it will use numeric type:
afloat = fields.Float()
afloat = fields.Float(digits=(32, 32))
afloat = fields.Float(digits=lambda cr: (32, 32))
Specific options:
digits: force use of numeric type on database. Parameter can be a tuple (int len, float len) or a callable that return a tuple and take a cursor as parameter
7.Date
Store date. The field provides some helpers:
adate = fields.Date()
context_today returns current day date string based on tz
today returns current system date string
from_string returns datetime.date() from string
to_string returns date string from datetime.date
:
>>> 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'
8.DateTime
Store datetime. The field provide some helper:
context_timestamp returns current day date string based on tz
now returns current system date string
from_string returns datetime.date() from string
to_string returns date string from datetime.date
:
>>> 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'
9.Binary (Multimedia Upload)
Store file encoded in base64 in bytea column:
abin = fields.Binary()
10.Selection
Store text in database but propose a selection widget. It induces no selection constraint in database. Selection must be set as a list of tuples or a callable that returns a list of tuples:
aselection = fields.Selection([('a', 'A')])
aselection = fields.Selection(selection=[('a', 'A')])
aselection = fields.Selection(selection='a_function_name')
Specific options:
selection: a list of tuple or a callable name that take recordset as input
When extending a model, if you want to add possible values to a selection field, you may use the selection_add keyword argument:
class SomeModel(models.Model):
_inherits = 'some.model'
type = fields.Selection(selection_add=[('b', 'B'), ('c', 'C')])
RELATIONAL FIELDS
1.Reference
Store an arbitrary reference to a model and a row:
aref = fields.Reference([('model_name', 'String')])
aref = fields.Reference(selection=[('model_name', 'String')])
aref = fields.Reference(selection='a_function_name')
Specific options:
selection: a list of tuple or a callable name that take recordset as input
2.Many2one (Select BOx)
Store a relation against a co-model:
arel_id = fields.Many2one('res.users')
arel_id = fields.Many2one(comodel_name='res.users')
an_other_rel_id = fields.Many2one(comodel_name='res.partner', delegate=True)
Specific options:
comodel_name: name of the opposite model
delegate: set it to True to make fields of the target model accessible from the current model (corresponds to _inherits)
3.One2many
Store a relation against many rows of co-model:
arel_ids = fields.One2many('res.users', 'rel_id')
arel_ids = fields.One2many(comodel_name='res.users', inverse_name='rel_id')
Specific options:
comodel_name: name of the opposite model
inverse_name: relational column of the opposite model (many2one field)
4.Many2many
Store a relation against many2many rows of co-model:
arel_ids = fields.Many2many('res.users')
arel_ids = fields.Many2many(comodel_name='res.users',
relation='table_name',
column1='col_name',
column2='other_col_name')
Specific options:
comodel_name: name of the opposite model
relation: relational table name (table_name_rel)
columns1: relational table left column name (model1_id)
columns2: relational table right column name(model2_id)
Fields Defaults
Default is now a keyword of a field:
You can attribute it a value or a function
name = fields.Char(default='A name')
# or
name = fields.Char(default=a_fun)
#...
def a_fun(self):
return self.do_something()
Computed Fields
There is no more direct creation of fields.function.
Instead you add a compute kwarg. The value is the name of the function as a string or a function. This allows to have fields definition atop of class:
class AModel(models.Model):
_name = 'a_name'
computed_total = fields.Float(compute='compute_total')
def compute_total(self):
...
self.computed_total = x
The function can be void. It should modify record property in order to be written to the cache:
self.name = new_value
Be aware that this assignation will trigger a write into the database. If you need to do bulk change or must be careful about performance, you should do classic call to write
To provide a search function on a non stored computed field you have to add a search kwarg on the field. The value is the name of the function as a string or a reference to a previously defined method. The function takes the second and third member of a domain tuple and returns a domain itself
def search_total(self, operator, operand):
...
return domain # e.g. [('id', 'in', ids)]
Inverse
The inverse key allows to trigger call of the decorated function when the field is written/”created”
Multi Fields
To have one function that compute multiple values:
@api.multi
@api.depends('field.relation', 'an_otherfield.relation')
def _amount(self):
for x in self:
x.total = an_algo
x.untaxed = an_algo
Related Field
There is not anymore fields.related fields.
Instead you just set the name argument related to your model:
participant_nick = fields.Char(string='Nick name',
related='partner_id.name')
The type kwarg is not needed anymore.
Setting the store kwarg will automatically store the value in database. With new API the value of the related field will be automatically updated, sweet.
participant_nick = fields.Char(string='Nick name',
store=True,
related='partner_id.name')
Note
When updating any related field not all translations of related field are translated if field is stored!!
Chained related fields modification will trigger invalidation of the cache for all elements of the chain.
Property Field
There is some use cases where value of the field must change depending of the current company.
To activate such behavior you can now use the company_dependent option.
A notable evolution in new API is that “property fields” are now searchable.
WIP copyable option
There is a dev running that will prevent to redefine copy by simply setting a copy option on fields:
copy=False # !! WIP to prevent redefine copy
0 comments:
Post a Comment