2
.. i18n: Objects, Fields and Methods
3
.. i18n: ===========================
6
Objects, Fields and Methods
7
===========================
9
.. i18n: OpenERP Objects
10
.. i18n: ---------------
16
.. i18n: .. This chapter is dedicated to detailed objects definition:
19
.. i18n: inheritancies
22
.. This chapter is dedicated to detailed objects definition:
27
.. i18n: All the ERP's pieces of data are accessible through "objects". As an example, there is a res.partner object to access the data concerning the partners, an account.invoice object for the data concerning the invoices, etc...
30
All the ERP's pieces of data are accessible through "objects". As an example, there is a res.partner object to access the data concerning the partners, an account.invoice object for the data concerning the invoices, etc...
32
.. i18n: Please note that there is an object for every type of resource, and not an
33
.. i18n: object per resource. We have thus a res.partner object to manage all the
34
.. i18n: partners and not a *res.partner* object per partner. If we talk in "object
35
.. i18n: oriented" terms, we could also say that there is an object per level.
38
Please note that there is an object for every type of resource, and not an
39
object per resource. We have thus a res.partner object to manage all the
40
partners and not a *res.partner* object per partner. If we talk in "object
41
oriented" terms, we could also say that there is an object per level.
43
.. i18n: The direct consequences is that all the methods of objects have a common parameter: the "ids" parameter. This specifies on which resources (for example, on which partner) the method must be applied. Precisely, this parameter contains a list of resource ids on which the method must be applied.
46
The direct consequences is that all the methods of objects have a common parameter: the "ids" parameter. This specifies on which resources (for example, on which partner) the method must be applied. Precisely, this parameter contains a list of resource ids on which the method must be applied.
48
.. i18n: For example, if we have two partners with the identifiers 1 and 5, and we want to call the res_partner method "send_email", we will write something like::
50
.. i18n: res_partner.send_email(... , [1, 5], ...)
53
For example, if we have two partners with the identifiers 1 and 5, and we want to call the res_partner method "send_email", we will write something like::
55
res_partner.send_email(... , [1, 5], ...)
57
.. i18n: We will see the exact syntax of object method calls further in this document.
60
We will see the exact syntax of object method calls further in this document.
62
.. i18n: In the following section, we will see how to define a new object. Then, we will check out the different methods of doing this.
65
In the following section, we will see how to define a new object. Then, we will check out the different methods of doing this.
67
.. i18n: For developers:
72
.. i18n: * OpenERP "objects" are usually called classes in object oriented programming.
73
.. i18n: * A OpenERP "resource" is usually called an object in OO programming, instance of a class.
76
* OpenERP "objects" are usually called classes in object oriented programming.
77
* A OpenERP "resource" is usually called an object in OO programming, instance of a class.
79
.. i18n: It's a bit confusing when you try to program inside OpenERP, because the language used is Python, and Python is a fully object oriented language, and has objects and instances ...
82
It's a bit confusing when you try to program inside OpenERP, because the language used is Python, and Python is a fully object oriented language, and has objects and instances ...
84
.. i18n: Luckily, an OpenERP "resource" can be converted magically into a nice Python object using the "browse" class method (OpenERP object method).
87
Luckily, an OpenERP "resource" can be converted magically into a nice Python object using the "browse" class method (OpenERP object method).
89
.. i18n: The ORM - Object-relational mapping - Models
90
.. i18n: --------------------------------------------
93
The ORM - Object-relational mapping - Models
94
--------------------------------------------
96
.. i18n: The ORM, short for Object-Relational Mapping, is a central part of OpenERP.
99
The ORM, short for Object-Relational Mapping, is a central part of OpenERP.
101
.. i18n: In OpenERP, the data model is described and manipulated through Python classes
102
.. i18n: and objects. It is the ORM job to bridge the gap -- as transparently as
103
.. i18n: possible for the developer -- between Python and the underlying relational
104
.. i18n: database (PostgreSQL), which will provide the persistence we need for our
108
In OpenERP, the data model is described and manipulated through Python classes
109
and objects. It is the ORM job to bridge the gap -- as transparently as
110
possible for the developer -- between Python and the underlying relational
111
database (PostgreSQL), which will provide the persistence we need for our
114
.. i18n: OpenERP Object Attributes
115
.. i18n: -------------------------
118
OpenERP Object Attributes
119
-------------------------
121
.. i18n: Objects Introduction
122
.. i18n: ++++++++++++++++++++
128
.. i18n: To define a new object, you must define a new Python class then instantiate it. This class must inherit from the osv class in the osv module.
131
To define a new object, you must define a new Python class then instantiate it. This class must inherit from the osv class in the osv module.
133
.. i18n: Object definition
134
.. i18n: +++++++++++++++++
140
.. i18n: The first line of the object definition will always be of the form::
142
.. i18n: class name_of_the_object(osv.osv):
143
.. i18n: _name = 'name.of.the.object'
144
.. i18n: _columns = { ... }
146
.. i18n: name_of_the_object()
149
The first line of the object definition will always be of the form::
151
class name_of_the_object(osv.osv):
152
_name = 'name.of.the.object'
157
.. i18n: An object is defined by declaring some fields with predefined names in the
158
.. i18n: class. Two of them are required (_name and _columns), the rest are optional.
159
.. i18n: The predefined fields are:
162
An object is defined by declaring some fields with predefined names in the
163
class. Two of them are required (_name and _columns), the rest are optional.
164
The predefined fields are:
166
.. i18n: Predefined fields
167
.. i18n: +++++++++++++++++
174
.. i18n: Determines whether a corresponding PostgreSQL table must be generated
175
.. i18n: automatically from the object. Setting _auto to False can be useful in case
176
.. i18n: of OpenERP objects generated from PostgreSQL views. See the "Reporting From
177
.. i18n: PostgreSQL Views" section for more details.
181
Determines whether a corresponding PostgreSQL table must be generated
182
automatically from the object. Setting _auto to False can be useful in case
183
of OpenERP objects generated from PostgreSQL views. See the "Reporting From
184
PostgreSQL Views" section for more details.
186
.. i18n: `_columns (required)`
187
.. i18n: The object fields. See the :ref:`fields <fields-link>` section for further details.
190
`_columns (required)`
191
The object fields. See the :ref:`fields <fields-link>` section for further details.
193
.. i18n: `_constraints`
194
.. i18n: The constraints on the object. See the constraints section for details.
198
The constraints on the object. See the constraints section for details.
200
.. i18n: `_sql_constraints`
201
.. i18n: The SQL Constraint on the object. See the SQL constraints section for further details.
205
The SQL Constraint on the object. See the SQL constraints section for further details.
208
.. i18n: The default values for some of the object's fields. See the default value section for details.
212
The default values for some of the object's fields. See the default value section for details.
215
.. i18n: The name of the osv object which the current object inherits from. See the :ref:`object inheritance section<inherit-link>`
216
.. i18n: (first form) for further details.
220
The name of the osv object which the current object inherits from. See the :ref:`object inheritance section<inherit-link>`
221
(first form) for further details.
224
.. i18n: The list of osv objects the object inherits from. This list must be given in
225
.. i18n: a python dictionary of the form: {'name_of_the_parent_object':
226
.. i18n: 'name_of_the_field', ...}. See the :ref:`object inheritance section<inherits-link>`
227
.. i18n: (second form) for further details. Default value: {}.
231
The list of osv objects the object inherits from. This list must be given in
232
a python dictionary of the form: {'name_of_the_parent_object':
233
'name_of_the_field', ...}. See the :ref:`object inheritance section<inherits-link>`
234
(second form) for further details. Default value: {}.
236
.. i18n: `_log_access`
237
.. i18n: Determines whether or not the write access to the resource must be logged.
238
.. i18n: If true, four fields will be created in the SQL table: create_uid,
239
.. i18n: create_date, write_uid, write_date. Those fields represent respectively the
240
.. i18n: id of the user who created the record, the creation date of record, the id
241
.. i18n: of the user who last modified the record, and the date of that last
242
.. i18n: modification. This data may be obtained by using the perm_read method.
246
Determines whether or not the write access to the resource must be logged.
247
If true, four fields will be created in the SQL table: create_uid,
248
create_date, write_uid, write_date. Those fields represent respectively the
249
id of the user who created the record, the creation date of record, the id
250
of the user who last modified the record, and the date of that last
251
modification. This data may be obtained by using the perm_read method.
253
.. i18n: `_name (required)`
254
.. i18n: Name of the object. Default value: None.
258
Name of the object. Default value: None.
261
.. i18n: Name of the fields used to sort the results of the search and read methods.
265
Name of the fields used to sort the results of the search and read methods.
267
.. i18n: Default value: 'id'.
274
.. i18n: _order = "name"
275
.. i18n: _order = "date_order desc"
281
_order = "date_order desc"
284
.. i18n: Name of the field in which the name of every resource is stored. Default
285
.. i18n: value: 'name'. Note: by default, the name_get method simply returns the
286
.. i18n: content of this field.
290
Name of the field in which the name of every resource is stored. Default
291
value: 'name'. Note: by default, the name_get method simply returns the
292
content of this field.
295
.. i18n: Name of the SQL sequence that manages the ids for this object. Default value: None.
299
Name of the SQL sequence that manages the ids for this object. Default value: None.
302
.. i18n: SQL code executed upon creation of the object (only if _auto is True). It means this code gets executed after the table is created.
306
SQL code executed upon creation of the object (only if _auto is True). It means this code gets executed after the table is created.
309
.. i18n: Name of the SQL table. Default value: the value of the _name field above
310
.. i18n: with the dots ( . ) replaced by underscores ( _ ).
314
Name of the SQL table. Default value: the value of the _name field above
315
with the dots ( . ) replaced by underscores ( _ ).
317
.. i18n: .. _inherit-link:
319
.. i18n: Object Inheritance - _inherit
320
.. i18n: -----------------------------
325
Object Inheritance - _inherit
326
-----------------------------
328
.. i18n: Introduction
329
.. i18n: ++++++++++++
335
.. i18n: Objects may be inherited in some custom or specific modules. It is better to
336
.. i18n: inherit an object to add/modify some fields.
339
Objects may be inherited in some custom or specific modules. It is better to
340
inherit an object to add/modify some fields.
342
.. i18n: It is done with::
344
.. i18n: _inherit='object.name'
349
_inherit='object.name'
351
.. i18n: Extension of an object
352
.. i18n: ++++++++++++++++++++++
355
Extension of an object
356
++++++++++++++++++++++
358
.. i18n: There are two possible ways to do this kind of inheritance. Both ways result in
359
.. i18n: a new class of data, which holds parent fields and behaviour as well as
360
.. i18n: additional fields and behaviour, but they differ in heavy programatical
361
.. i18n: consequences.
364
There are two possible ways to do this kind of inheritance. Both ways result in
365
a new class of data, which holds parent fields and behaviour as well as
366
additional fields and behaviour, but they differ in heavy programatical
369
.. i18n: While Example 1 creates a new subclass "custom_material" that may be "seen" or
370
.. i18n: "used" by any view or tree which handles "network.material", this will not be
371
.. i18n: the case for Example 2.
374
While Example 1 creates a new subclass "custom_material" that may be "seen" or
375
"used" by any view or tree which handles "network.material", this will not be
376
the case for Example 2.
378
.. i18n: This is due to the table (other.material) the new subclass is operating on,
379
.. i18n: which will never be recognized by previous "network.material" views or trees.
382
This is due to the table (other.material) the new subclass is operating on,
383
which will never be recognized by previous "network.material" views or trees.
387
.. i18n: class custom_material(osv.osv):
388
.. i18n: _name = 'network.material'
389
.. i18n: _inherit = 'network.material'
390
.. i18n: _columns = {
391
.. i18n: 'manuf_warranty': fields.boolean('Manufacturer warranty?'),
393
.. i18n: _defaults = {
394
.. i18n: 'manuf_warranty': lambda *a: False,
396
.. i18n: custom_material()
401
class custom_material(osv.osv):
402
_name = 'network.material'
403
_inherit = 'network.material'
405
'manuf_warranty': fields.boolean('Manufacturer warranty?'),
408
'manuf_warranty': lambda *a: False,
412
.. i18n: .. tip:: Notice
414
.. i18n: _name == _inherit
421
.. i18n: In this example, the 'custom_material' will add a new field 'manuf_warranty' to
422
.. i18n: the object 'network.material'. New instances of this class will be visible by
423
.. i18n: views or trees operating on the superclasses table 'network.material'.
426
In this example, the 'custom_material' will add a new field 'manuf_warranty' to
427
the object 'network.material'. New instances of this class will be visible by
428
views or trees operating on the superclasses table 'network.material'.
430
.. i18n: This inheritancy is usually called "class inheritance" in Object oriented
431
.. i18n: design. The child inherits data (fields) and behavior (functions) of his
435
This inheritancy is usually called "class inheritance" in Object oriented
436
design. The child inherits data (fields) and behavior (functions) of his
441
.. i18n: class other_material(osv.osv):
442
.. i18n: _name = 'other.material'
443
.. i18n: _inherit = 'network.material'
444
.. i18n: _columns = {
445
.. i18n: 'manuf_warranty': fields.boolean('Manufacturer warranty?'),
447
.. i18n: _defaults = {
448
.. i18n: 'manuf_warranty': lambda *a: False,
450
.. i18n: other_material()
455
class other_material(osv.osv):
456
_name = 'other.material'
457
_inherit = 'network.material'
459
'manuf_warranty': fields.boolean('Manufacturer warranty?'),
462
'manuf_warranty': lambda *a: False,
466
.. i18n: .. tip:: Notice
468
.. i18n: _name != _inherit
475
.. i18n: In this example, the 'other_material' will hold all fields specified by
476
.. i18n: 'network.material' and it will additionally hold a new field 'manuf_warranty'.
477
.. i18n: All those fields will be part of the table 'other.material'. New instances of
478
.. i18n: this class will therefore never been seen by views or trees operating on the
479
.. i18n: superclasses table 'network.material'.
482
In this example, the 'other_material' will hold all fields specified by
483
'network.material' and it will additionally hold a new field 'manuf_warranty'.
484
All those fields will be part of the table 'other.material'. New instances of
485
this class will therefore never been seen by views or trees operating on the
486
superclasses table 'network.material'.
488
.. i18n: This type of inheritancy is known as "inheritance by prototyping" (e.g.
489
.. i18n: Javascript), because the newly created subclass "copies" all fields from the
490
.. i18n: specified superclass (prototype). The child inherits data (fields) and behavior
491
.. i18n: (functions) of his parent.
494
This type of inheritancy is known as "inheritance by prototyping" (e.g.
495
Javascript), because the newly created subclass "copies" all fields from the
496
specified superclass (prototype). The child inherits data (fields) and behavior
497
(functions) of his parent.
499
.. i18n: .. _inherits-link:
501
.. i18n: Inheritance by Delegation - _inherits
502
.. i18n: -------------------------------------
507
Inheritance by Delegation - _inherits
508
-------------------------------------
510
.. i18n: **Syntax :**::
512
.. i18n: class tiny_object(osv.osv)
513
.. i18n: _name = 'tiny.object'
514
.. i18n: _table = 'tiny_object'
515
.. i18n: _inherits = {
516
.. i18n: 'tiny.object_a': 'object_a_id',
517
.. i18n: 'tiny.object_b': 'object_b_id',
519
.. i18n: 'tiny.object_n': 'object_n_id'
526
class tiny_object(osv.osv)
527
_name = 'tiny.object'
528
_table = 'tiny_object'
530
'tiny.object_a': 'object_a_id',
531
'tiny.object_b': 'object_b_id',
533
'tiny.object_n': 'object_n_id'
537
.. i18n: The object 'tiny.object' inherits from all the columns and all the methods from
538
.. i18n: the n objects 'tiny.object_a', ..., 'tiny.object_n'.
541
The object 'tiny.object' inherits from all the columns and all the methods from
542
the n objects 'tiny.object_a', ..., 'tiny.object_n'.
544
.. i18n: To inherit from multiple tables, the technique consists in adding one column to
545
.. i18n: the table tiny_object per inherited object. This column will store a foreign
546
.. i18n: key (an id from another table). The values *'object_a_id' 'object_b_id' ...
547
.. i18n: 'object_n_id'* are of type string and determine the title of the columns in
548
.. i18n: which the foreign keys from 'tiny.object_a', ..., 'tiny.object_n' are stored.
551
To inherit from multiple tables, the technique consists in adding one column to
552
the table tiny_object per inherited object. This column will store a foreign
553
key (an id from another table). The values *'object_a_id' 'object_b_id' ...
554
'object_n_id'* are of type string and determine the title of the columns in
555
which the foreign keys from 'tiny.object_a', ..., 'tiny.object_n' are stored.
557
.. i18n: This inheritance mechanism is usually called " *instance inheritance* " or "
558
.. i18n: *value inheritance* ". A resource (instance) has the VALUES of its parents.
561
This inheritance mechanism is usually called " *instance inheritance* " or "
562
*value inheritance* ". A resource (instance) has the VALUES of its parents.
564
.. i18n: .. _fields-link:
566
.. i18n: Fields Introduction
567
.. i18n: -------------------
575
.. i18n: Objects may contain different types of fields. Those types can be divided into
576
.. i18n: three categories: simple types, relation types and functional fields. The
577
.. i18n: simple types are integers, floats, booleans, strings, etc ... ; the relation
578
.. i18n: types are used to represent relations between objects (one2one, one2many,
579
.. i18n: many2one). Functional fields are special fields because they are not stored in
580
.. i18n: the database but calculated in real time given other fields of the view.
583
Objects may contain different types of fields. Those types can be divided into
584
three categories: simple types, relation types and functional fields. The
585
simple types are integers, floats, booleans, strings, etc ... ; the relation
586
types are used to represent relations between objects (one2one, one2many,
587
many2one). Functional fields are special fields because they are not stored in
588
the database but calculated in real time given other fields of the view.
590
.. i18n: Here's the header of the initialization method of the class any field defined
591
.. i18n: in OpenERP inherits (as you can see in server/bin/osv/fields.py)::
593
.. i18n: def __init__(self, string='unknown', required=False, readonly=False,
594
.. i18n: domain=None, context="", states=None, priority=0, change_default=False, size=None,
595
.. i18n: ondelete="set null", translate=False, select=False, **args) :
598
Here's the header of the initialization method of the class any field defined
599
in OpenERP inherits (as you can see in server/bin/osv/fields.py)::
601
def __init__(self, string='unknown', required=False, readonly=False,
602
domain=None, context="", states=None, priority=0, change_default=False, size=None,
603
ondelete="set null", translate=False, select=False, **args) :
605
.. i18n: There are a common set of optional parameters that are available to most field
609
There are a common set of optional parameters that are available to most field
612
.. i18n: :change_default:
613
.. i18n: Whether or not the user can define default values on other fields depending
614
.. i18n: on the value of this field. Those default values need to be defined in
615
.. i18n: the ir.values table.
617
.. i18n: A description of how the field should be used: longer and more descriptive
618
.. i18n: than `string`. It will appear in a tooltip when the mouse hovers over the
621
.. i18n: How to handle deletions in a related record. Allowable values are:
622
.. i18n: 'restrict', 'no action', 'cascade', 'set null', and 'set default'.
623
.. i18n: :priority: Not used?
624
.. i18n: :readonly: `True` if the user cannot edit this field, otherwise `False`.
626
.. i18n: `True` if this field must have a value before the object can be saved,
627
.. i18n: otherwise `False`.
628
.. i18n: :size: The size of the field in the database: number characters or digits.
630
.. i18n: Lets you override other parameters for specific states of this object.
631
.. i18n: Accepts a dictionary with the state names as keys and a list of name/value
632
.. i18n: tuples as the values. For example: `states={'posted':[('readonly',True)]}`
634
.. i18n: The field name as it should appear in a label or column header. Strings
635
.. i18n: containing non-ASCII characters must use python unicode objects.
636
.. i18n: For example: `'tested': fields.boolean(u'Testé')`
638
.. i18n: `True` if the *content* of this field should be translated, otherwise
643
Whether or not the user can define default values on other fields depending
644
on the value of this field. Those default values need to be defined in
647
A description of how the field should be used: longer and more descriptive
648
than `string`. It will appear in a tooltip when the mouse hovers over the
651
How to handle deletions in a related record. Allowable values are:
652
'restrict', 'no action', 'cascade', 'set null', and 'set default'.
654
:readonly: `True` if the user cannot edit this field, otherwise `False`.
656
`True` if this field must have a value before the object can be saved,
658
:size: The size of the field in the database: number characters or digits.
660
Lets you override other parameters for specific states of this object.
661
Accepts a dictionary with the state names as keys and a list of name/value
662
tuples as the values. For example: `states={'posted':[('readonly',True)]}`
664
The field name as it should appear in a label or column header. Strings
665
containing non-ASCII characters must use python unicode objects.
666
For example: `'tested': fields.boolean(u'Testé')`
668
`True` if the *content* of this field should be translated, otherwise
671
.. i18n: There are also some optional parameters that are specific to some field types:
674
There are also some optional parameters that are specific to some field types:
677
.. i18n: Define a variable's value visible in the view's context or an on-change
678
.. i18n: function. Used when searching child table of `one2many` relationship?
680
.. i18n: Domain restriction on a relational field.
684
Define a variable's value visible in the view's context or an on-change
685
function. Used when searching child table of `one2many` relationship?
687
Domain restriction on a relational field.
689
.. i18n: Default value: [].
694
.. i18n: Example: domain=[('field','=',value)])
695
.. i18n: :invisible: Hide the field's value in forms. For example, a password.
697
.. i18n: Default value for the `on_change` attribute in the view. This will launch
698
.. i18n: a function on the server when the field changes in the client. For example,
699
.. i18n: `on_change="onchange_shop_id(shop_id)"`.
701
.. i18n: Used when a field is an id reference to another table. This is the name of
702
.. i18n: the table to look in. Most commonly used with related and function field
705
.. i18n: Default value for the `select` attribute in the view. 1 means basic search,
706
.. i18n: and 2 means advanced search.
709
Example: domain=[('field','=',value)])
710
:invisible: Hide the field's value in forms. For example, a password.
712
Default value for the `on_change` attribute in the view. This will launch
713
a function on the server when the field changes in the client. For example,
714
`on_change="onchange_shop_id(shop_id)"`.
716
Used when a field is an id reference to another table. This is the name of
717
the table to look in. Most commonly used with related and function field
720
Default value for the `select` attribute in the view. 1 means basic search,
721
and 2 means advanced search.
723
.. i18n: Type of Fields
724
.. i18n: --------------
742
.. i18n: A boolean (true, false).
745
A boolean (true, false).
749
.. i18n: fields.boolean('Field Name' [, Optional Parameters]),
754
fields.boolean('Field Name' [, Optional Parameters]),
768
.. i18n: fields.integer('Field Name' [, Optional Parameters]),
773
fields.integer('Field Name' [, Optional Parameters]),
780
.. i18n: A floating point number.
783
A floating point number.
787
.. i18n: fields.float('Field Name' [, Optional Parameters]),
791
.. i18n: The optional parameter digits defines the precision and scale of the
792
.. i18n: number. The scale being the number of digits after the decimal point
793
.. i18n: whereas the precision is the total number of significant digits in the
794
.. i18n: number (before and after the decimal point). If the parameter digits is
795
.. i18n: not present, the number will be a double precision floating point number.
796
.. i18n: Warning: these floating-point numbers are inexact (not any value can be
797
.. i18n: converted to its binary representation) and this can lead to rounding
798
.. i18n: errors. You should always use the digits parameter for monetary amounts.
802
.. i18n: 'rate': fields.float(
803
.. i18n: 'Relative Change rate',
804
.. i18n: digits=(12,6) [,
805
.. i18n: Optional Parameters]),
810
fields.float('Field Name' [, Optional Parameters]),
814
The optional parameter digits defines the precision and scale of the
815
number. The scale being the number of digits after the decimal point
816
whereas the precision is the total number of significant digits in the
817
number (before and after the decimal point). If the parameter digits is
818
not present, the number will be a double precision floating point number.
819
Warning: these floating-point numbers are inexact (not any value can be
820
converted to its binary representation) and this can lead to rounding
821
errors. You should always use the digits parameter for monetary amounts.
825
'rate': fields.float(
826
'Relative Change rate',
828
Optional Parameters]),
835
.. i18n: A string of limited length. The required size parameter determines its size.
838
A string of limited length. The required size parameter determines its size.
842
.. i18n: fields.char(
843
.. i18n: 'Field Name',
845
.. i18n: Optional Parameters]), # where ''n'' is an integer.
849
.. i18n: 'city' : fields.char('City Name', size=30, required=True),
857
Optional Parameters]), # where ''n'' is an integer.
861
'city' : fields.char('City Name', size=30, required=True),
868
.. i18n: A text field with no limit in length.
871
A text field with no limit in length.
875
.. i18n: fields.text('Field Name' [, Optional Parameters]),
880
fields.text('Field Name' [, Optional Parameters]),
894
.. i18n: fields.date('Field Name' [, Optional Parameters]),
899
fields.date('Field Name' [, Optional Parameters]),
906
.. i18n: Allows to store a date and the time of day in the same field.
909
Allows to store a date and the time of day in the same field.
913
.. i18n: fields.datetime('Field Name' [, Optional Parameters]),
918
fields.datetime('Field Name' [, Optional Parameters]),
925
.. i18n: A binary chain
935
.. i18n: A field which allows the user to make a selection between various predefined values.
938
A field which allows the user to make a selection between various predefined values.
942
.. i18n: fields.selection((('n','Unconfirmed'), ('c','Confirmed')),
943
.. i18n: 'Field Name' [, Optional Parameters]),
947
.. i18n: Format of the selection parameter: tuple of tuples of strings of the form::
949
.. i18n: (('key_or_value', 'string_to_display'), ... )
952
.. i18n: You can specify a function that will return the tuple. Example ::
954
.. i18n: def _get_selection(self, cursor, user_id, context=None):
956
.. i18n: ('choice1', 'This is the choice 1'),
957
.. i18n: ('choice2', 'This is the choice 2'))
959
.. i18n: _columns = {
960
.. i18n: 'sel' : fields.selection(
961
.. i18n: _get_selection,
962
.. i18n: 'What do you want ?')
967
.. i18n: Using relation fields **many2one** with **selection**. In fields definitions add::
970
.. i18n: 'my_field': fields.many2one(
971
.. i18n: 'mymodule.relation.model',
973
.. i18n: selection=_sel_func),
976
.. i18n: And then define the _sel_func like this (but before the fields definitions)::
978
.. i18n: def _sel_func(self, cr, uid, context=None):
979
.. i18n: obj = self.pool.get('mymodule.relation.model')
980
.. i18n: ids = obj.search(cr, uid, [])
981
.. i18n: res = obj.read(cr, uid, ids, ['name', 'id'], context)
982
.. i18n: res = [(r['id'], r['name']) for r in res]
988
fields.selection((('n','Unconfirmed'), ('c','Confirmed')),
989
'Field Name' [, Optional Parameters]),
993
Format of the selection parameter: tuple of tuples of strings of the form::
995
(('key_or_value', 'string_to_display'), ... )
998
You can specify a function that will return the tuple. Example ::
1000
def _get_selection(self, cursor, user_id, context=None):
1002
('choice1', 'This is the choice 1'),
1003
('choice2', 'This is the choice 2'))
1006
'sel' : fields.selection(
1008
'What do you want ?')
1013
Using relation fields **many2one** with **selection**. In fields definitions add::
1016
'my_field': fields.many2one(
1017
'mymodule.relation.model',
1019
selection=_sel_func),
1022
And then define the _sel_func like this (but before the fields definitions)::
1024
def _sel_func(self, cr, uid, context=None):
1025
obj = self.pool.get('mymodule.relation.model')
1026
ids = obj.search(cr, uid, [])
1027
res = obj.read(cr, uid, ids, ['name', 'id'], context)
1028
res = [(r['id'], r['name']) for r in res]
1031
.. i18n: Relational Types
1032
.. i18n: ++++++++++++++++
1043
.. i18n: A one2one field expresses a one:to:one relation between two objects. It is
1044
.. i18n: deprecated. Use many2one instead.
1047
A one2one field expresses a one:to:one relation between two objects. It is
1048
deprecated. Use many2one instead.
1052
.. i18n: fields.one2one('other.object.name', 'Field Name')
1057
fields.one2one('other.object.name', 'Field Name')
1064
.. i18n: Associates this object to a parent object via this Field. For example
1065
.. i18n: Department an Employee belongs to would Many to one. i.e Many employees will
1066
.. i18n: belong to a Department
1069
Associates this object to a parent object via this Field. For example
1070
Department an Employee belongs to would Many to one. i.e Many employees will
1071
belong to a Department
1075
.. i18n: fields.many2one(
1076
.. i18n: 'other.object.name',
1077
.. i18n: 'Field Name',
1078
.. i18n: optional parameters)
1080
.. i18n: Optional parameters:
1082
.. i18n: - ondelete: What should happen when the resource this field points to is deleted.
1083
.. i18n: + Predefined value: "cascade", "set null", "restrict", "no action", "set default"
1084
.. i18n: + Default value: "set null"
1085
.. i18n: - required: True
1086
.. i18n: - readonly: True
1087
.. i18n: - select: True - (creates an index on the Foreign Key field)
1089
.. i18n: *Example* ::
1091
.. i18n: 'commercial': fields.many2one(
1092
.. i18n: 'res.users',
1093
.. i18n: 'Commercial',
1094
.. i18n: ondelete='cascade'),
1100
'other.object.name',
1102
optional parameters)
1104
Optional parameters:
1106
- ondelete: What should happen when the resource this field points to is deleted.
1107
+ Predefined value: "cascade", "set null", "restrict", "no action", "set default"
1108
+ Default value: "set null"
1111
- select: True - (creates an index on the Foreign Key field)
1115
'commercial': fields.many2one(
1118
ondelete='cascade'),
1132
.. i18n: fields.one2many(
1133
.. i18n: 'other.object.name',
1134
.. i18n: 'Field relation id',
1135
.. i18n: 'Fieldname',
1136
.. i18n: optional parameter)
1138
.. i18n: Optional parameters:
1139
.. i18n: - invisible: True/False
1140
.. i18n: - states: ?
1141
.. i18n: - readonly: True/False
1143
.. i18n: *Example* ::
1145
.. i18n: 'address': fields.one2many(
1146
.. i18n: 'res.partner.address',
1147
.. i18n: 'partner_id',
1148
.. i18n: 'Contacts'),
1154
'other.object.name',
1155
'Field relation id',
1159
Optional parameters:
1160
- invisible: True/False
1162
- readonly: True/False
1166
'address': fields.one2many(
1167
'res.partner.address',
1171
.. i18n: :many2many:
1183
.. i18n: fields.many2many('other.object.name',
1184
.. i18n: 'relation object',
1185
.. i18n: 'actual.object.id',
1186
.. i18n: 'other.object.id',
1187
.. i18n: 'Field Name')
1190
.. i18n: - other.object.name is the other object which belongs to the relation
1191
.. i18n: - relation object is the table that makes the link
1192
.. i18n: - actual.object.id and other.object.id are the fields' names used in the relation table
1196
.. i18n: 'category_ids':
1197
.. i18n: fields.many2many(
1198
.. i18n: 'res.partner.category',
1199
.. i18n: 'res_partner_category_rel',
1200
.. i18n: 'partner_id',
1201
.. i18n: 'category_id',
1202
.. i18n: 'Categories'),
1204
.. i18n: To make it bidirectional (= create a field in the other object)::
1206
.. i18n: class other_object_name2(osv.osv):
1207
.. i18n: _inherit = 'other.object.name'
1208
.. i18n: _columns = {
1209
.. i18n: 'other_fields': fields.many2many(
1210
.. i18n: 'actual.object.name',
1211
.. i18n: 'relation object',
1212
.. i18n: 'actual.object.id',
1213
.. i18n: 'other.object.id',
1214
.. i18n: 'Other Field Name'),
1216
.. i18n: other_object_name2()
1220
.. i18n: class res_partner_category2(osv.osv):
1221
.. i18n: _inherit = 'res.partner.category'
1222
.. i18n: _columns = {
1223
.. i18n: 'partner_ids': fields.many2many(
1224
.. i18n: 'res.partner',
1225
.. i18n: 'res_partner_category_rel',
1226
.. i18n: 'category_id',
1227
.. i18n: 'partner_id',
1228
.. i18n: 'Partners'),
1230
.. i18n: res_partner_category2()
1235
fields.many2many('other.object.name',
1242
- other.object.name is the other object which belongs to the relation
1243
- relation object is the table that makes the link
1244
- actual.object.id and other.object.id are the fields' names used in the relation table
1250
'res.partner.category',
1251
'res_partner_category_rel',
1256
To make it bidirectional (= create a field in the other object)::
1258
class other_object_name2(osv.osv):
1259
_inherit = 'other.object.name'
1261
'other_fields': fields.many2many(
1262
'actual.object.name',
1266
'Other Field Name'),
1268
other_object_name2()
1272
class res_partner_category2(osv.osv):
1273
_inherit = 'res.partner.category'
1275
'partner_ids': fields.many2many(
1277
'res_partner_category_rel',
1282
res_partner_category2()
1289
.. i18n: Sometimes you need to refer to the relation of a relation. For example,
1290
.. i18n: supposing you have objects: City -> State -> Country, and you need to refer to
1291
.. i18n: the Country from a City, you can define a field as below in the City object::
1293
.. i18n: 'country_id': fields.related(
1294
.. i18n: 'state_id',
1295
.. i18n: 'country_id',
1296
.. i18n: type="many2one",
1297
.. i18n: relation="res.country",
1298
.. i18n: string="Country",
1299
.. i18n: store=False)
1302
.. i18n: - The first set of parameters are the chain of reference fields to
1303
.. i18n: follow, with the desired field at the end.
1304
.. i18n: - :guilabel:`type` is the type of that desired field.
1305
.. i18n: - Use :guilabel:`relation` if the desired field is still some kind of
1306
.. i18n: reference. :guilabel:`relation` is the table to look up that
1307
.. i18n: reference in.
1310
Sometimes you need to refer to the relation of a relation. For example,
1311
supposing you have objects: City -> State -> Country, and you need to refer to
1312
the Country from a City, you can define a field as below in the City object::
1314
'country_id': fields.related(
1318
relation="res.country",
1323
- The first set of parameters are the chain of reference fields to
1324
follow, with the desired field at the end.
1325
- :guilabel:`type` is the type of that desired field.
1326
- Use :guilabel:`relation` if the desired field is still some kind of
1327
reference. :guilabel:`relation` is the table to look up that
1330
.. i18n: Functional Fields
1331
.. i18n: +++++++++++++++++
1337
.. i18n: A functional field is a field whose value is calculated by a function (rather
1338
.. i18n: than being stored in the database).
1341
A functional field is a field whose value is calculated by a function (rather
1342
than being stored in the database).
1344
.. i18n: **Parameters:** ::
1346
.. i18n: fnct, arg=None, fnct_inv=None, fnct_inv_arg=None, type="float",
1347
.. i18n: fnct_search=None, obj=None, method=False, store=False, multi=False
1352
fnct, arg=None, fnct_inv=None, fnct_inv_arg=None, type="float",
1353
fnct_search=None, obj=None, method=False, store=False, multi=False
1360
.. i18n: * :guilabel:`fnct` is the function or method that will compute the field
1361
.. i18n: value. It must have been declared before declaring the functional field.
1362
.. i18n: * :guilabel:`fnct_inv` is the function or method that will allow writing
1363
.. i18n: values in that field.
1364
.. i18n: * :guilabel:`type` is the field type name returned by the function. It can
1365
.. i18n: be any field type name except function.
1366
.. i18n: * :guilabel:`fnct_search` allows you to define the searching behaviour on
1367
.. i18n: that field.
1368
.. i18n: * :guilabel:`method` whether the field is computed by a method (of an
1369
.. i18n: object) or a global function
1370
.. i18n: * :guilabel:`store` If you want to store field in database or not. Default
1372
.. i18n: * :guilabel:`multi` is a group name. All fields with the same `multi`
1373
.. i18n: parameter will be calculated in a single function call.
1376
* :guilabel:`fnct` is the function or method that will compute the field
1377
value. It must have been declared before declaring the functional field.
1378
* :guilabel:`fnct_inv` is the function or method that will allow writing
1379
values in that field.
1380
* :guilabel:`type` is the field type name returned by the function. It can
1381
be any field type name except function.
1382
* :guilabel:`fnct_search` allows you to define the searching behaviour on
1384
* :guilabel:`method` whether the field is computed by a method (of an
1385
object) or a global function
1386
* :guilabel:`store` If you want to store field in database or not. Default
1388
* :guilabel:`multi` is a group name. All fields with the same `multi`
1389
parameter will be calculated in a single function call.
1391
.. i18n: fnct parameter
1392
.. i18n: """"""""""""""
1393
.. i18n: If *method* is True, the signature of the method must be::
1395
.. i18n: def fnct(self, cr, uid, ids, field_name, arg, context):
1400
If *method* is True, the signature of the method must be::
1402
def fnct(self, cr, uid, ids, field_name, arg, context):
1404
.. i18n: otherwise (if it is a global function), its signature must be::
1406
.. i18n: def fnct(cr, table, ids, field_name, arg, context):
1409
otherwise (if it is a global function), its signature must be::
1411
def fnct(cr, table, ids, field_name, arg, context):
1413
.. i18n: Either way, it must return a dictionary of values of the form
1414
.. i18n: **{id'_1_': value'_1_', id'_2_': value'_2_',...}.**
1417
Either way, it must return a dictionary of values of the form
1418
**{id'_1_': value'_1_', id'_2_': value'_2_',...}.**
1420
.. i18n: The values of the returned dictionary must be of the type specified by the type
1421
.. i18n: argument in the field declaration.
1424
The values of the returned dictionary must be of the type specified by the type
1425
argument in the field declaration.
1427
.. i18n: If *multi* is set, then *field_name* is replaced by *field_names*: a list
1428
.. i18n: of the field names that should be calculated. Each value in the returned
1429
.. i18n: dictionary is also a dictionary from field name to value. For example, if the
1430
.. i18n: fields `'name'`, and `'age'` are both based on the `vital_statistics` function,
1431
.. i18n: then the return value of `vital_statistics` might look like this when `ids` is
1432
.. i18n: `[1, 2, 5]`::
1435
.. i18n: 1: {'name': 'Bob', 'age': 23},
1436
.. i18n: 2: {'name': 'Sally', 'age', 19},
1437
.. i18n: 5: {'name': 'Ed', 'age': 62}
1441
If *multi* is set, then *field_name* is replaced by *field_names*: a list
1442
of the field names that should be calculated. Each value in the returned
1443
dictionary is also a dictionary from field name to value. For example, if the
1444
fields `'name'`, and `'age'` are both based on the `vital_statistics` function,
1445
then the return value of `vital_statistics` might look like this when `ids` is
1449
1: {'name': 'Bob', 'age': 23},
1450
2: {'name': 'Sally', 'age', 19},
1451
5: {'name': 'Ed', 'age': 62}
1454
.. i18n: fnct_inv parameter
1455
.. i18n: """"""""""""""""""
1456
.. i18n: If *method* is true, the signature of the method must be::
1458
.. i18n: def fnct(self, cr, uid, ids, field_name, field_value, arg, context):
1464
If *method* is true, the signature of the method must be::
1466
def fnct(self, cr, uid, ids, field_name, field_value, arg, context):
1469
.. i18n: otherwise (if it is a global function), it should be::
1471
.. i18n: def fnct(cr, table, ids, field_name, field_value, arg, context):
1474
otherwise (if it is a global function), it should be::
1476
def fnct(cr, table, ids, field_name, field_value, arg, context):
1478
.. i18n: fnct_search parameter
1479
.. i18n: """""""""""""""""""""
1480
.. i18n: If method is true, the signature of the method must be::
1482
.. i18n: def fnct(self, cr, uid, obj, name, args, context):
1485
fnct_search parameter
1486
"""""""""""""""""""""
1487
If method is true, the signature of the method must be::
1489
def fnct(self, cr, uid, obj, name, args, context):
1491
.. i18n: otherwise (if it is a global function), it should be::
1493
.. i18n: def fnct(cr, uid, obj, name, args, context):
1496
otherwise (if it is a global function), it should be::
1498
def fnct(cr, uid, obj, name, args, context):
1500
.. i18n: The return value is a list containing 3-part tuples which are used in search function::
1502
.. i18n: return [('id','in',[1,3,5])]
1505
The return value is a list containing 3-part tuples which are used in search function::
1507
return [('id','in',[1,3,5])]
1509
.. i18n: *obj* is the same as *self*, and *name* receives the field name. *args* is a list
1510
.. i18n: of 3-part tuples containing search criteria for this field, although the search
1511
.. i18n: function may be called separately for each tuple.
1514
*obj* is the same as *self*, and *name* receives the field name. *args* is a list
1515
of 3-part tuples containing search criteria for this field, although the search
1516
function may be called separately for each tuple.
1520
.. i18n: Suppose we create a contract object which is :
1525
Suppose we create a contract object which is :
1527
.. i18n: .. code-block:: python
1529
.. i18n: class hr_contract(osv.osv):
1530
.. i18n: _name = 'hr.contract'
1531
.. i18n: _description = 'Contract'
1532
.. i18n: _columns = {
1533
.. i18n: 'name' : fields.char('Contract Name', size=30, required=True),
1534
.. i18n: 'employee_id' : fields.many2one('hr.employee', 'Employee', required=True),
1535
.. i18n: 'function' : fields.many2one('res.partner.function', 'Function'),
1537
.. i18n: hr_contract()
1540
.. code-block:: python
1542
class hr_contract(osv.osv):
1543
_name = 'hr.contract'
1544
_description = 'Contract'
1546
'name' : fields.char('Contract Name', size=30, required=True),
1547
'employee_id' : fields.many2one('hr.employee', 'Employee', required=True),
1548
'function' : fields.many2one('res.partner.function', 'Function'),
1552
.. i18n: If we want to add a field that retrieves the function of an employee by looking its current contract, we use a functional field. The object hr_employee is inherited this way:
1555
If we want to add a field that retrieves the function of an employee by looking its current contract, we use a functional field. The object hr_employee is inherited this way:
1557
.. i18n: .. code-block:: python
1559
.. i18n: class hr_employee(osv.osv):
1560
.. i18n: _name = "hr.employee"
1561
.. i18n: _description = "Employee"
1562
.. i18n: _inherit = "hr.employee"
1563
.. i18n: _columns = {
1564
.. i18n: 'contract_ids' : fields.one2many('hr.contract', 'employee_id', 'Contracts'),
1565
.. i18n: 'function' : fields.function(
1566
.. i18n: _get_cur_function_id,
1567
.. i18n: type='many2one',
1568
.. i18n: obj="res.partner.function",
1569
.. i18n: method=True,
1570
.. i18n: string='Contract Function'),
1572
.. i18n: hr_employee()
1575
.. code-block:: python
1577
class hr_employee(osv.osv):
1578
_name = "hr.employee"
1579
_description = "Employee"
1580
_inherit = "hr.employee"
1582
'contract_ids' : fields.one2many('hr.contract', 'employee_id', 'Contracts'),
1583
'function' : fields.function(
1584
_get_cur_function_id,
1586
obj="res.partner.function",
1588
string='Contract Function'),
1592
.. i18n: .. note:: three points
1594
.. i18n: * :guilabel:`type` ='many2one' is because the function field must create
1595
.. i18n: a many2one field; function is declared as a many2one in hr_contract also.
1596
.. i18n: * :guilabel:`obj` ="res.partner.function" is used to specify that the
1597
.. i18n: object to use for the many2one field is res.partner.function.
1598
.. i18n: * We called our method :guilabel:`_get_cur_function_id` because its role
1599
.. i18n: is to return a dictionary whose keys are ids of employees, and whose
1600
.. i18n: corresponding values are ids of the function of those employees. The
1601
.. i18n: code of this method is:
1604
.. note:: three points
1606
* :guilabel:`type` ='many2one' is because the function field must create
1607
a many2one field; function is declared as a many2one in hr_contract also.
1608
* :guilabel:`obj` ="res.partner.function" is used to specify that the
1609
object to use for the many2one field is res.partner.function.
1610
* We called our method :guilabel:`_get_cur_function_id` because its role
1611
is to return a dictionary whose keys are ids of employees, and whose
1612
corresponding values are ids of the function of those employees. The
1613
code of this method is:
1615
.. i18n: .. code-block:: python
1617
.. i18n: def _get_cur_function_id(self, cr, uid, ids, field_name, arg, context):
1618
.. i18n: for i in ids:
1619
.. i18n: #get the id of the current function of the employee of identifier "i"
1620
.. i18n: sql_req= """
1621
.. i18n: SELECT f.id AS func_id
1622
.. i18n: FROM hr_contract c
1623
.. i18n: LEFT JOIN res_partner_function f ON (f.id = c.function)
1625
.. i18n: (c.employee_id = %d)
1628
.. i18n: cr.execute(sql_req)
1629
.. i18n: sql_res = cr.dictfetchone()
1631
.. i18n: if sql_res: #The employee has one associated contract
1632
.. i18n: res[i] = sql_res['func_id']
1634
.. i18n: #res[i] must be set to False and not to None because of XML:RPC
1635
.. i18n: # "cannot marshal None unless allow_none is enabled"
1636
.. i18n: res[i] = False
1640
.. code-block:: python
1642
def _get_cur_function_id(self, cr, uid, ids, field_name, arg, context):
1644
#get the id of the current function of the employee of identifier "i"
1646
SELECT f.id AS func_id
1648
LEFT JOIN res_partner_function f ON (f.id = c.function)
1650
(c.employee_id = %d)
1654
sql_res = cr.dictfetchone()
1656
if sql_res: #The employee has one associated contract
1657
res[i] = sql_res['func_id']
1659
#res[i] must be set to False and not to None because of XML:RPC
1660
# "cannot marshal None unless allow_none is enabled"
1664
.. i18n: The id of the function is retrieved using a SQL query. Note that if the query
1665
.. i18n: returns no result, the value of sql_res['func_id'] will be None. We force the
1666
.. i18n: False value in this case value because XML:RPC (communication between the server
1667
.. i18n: and the client) doesn't allow to transmit this value.
1670
The id of the function is retrieved using a SQL query. Note that if the query
1671
returns no result, the value of sql_res['func_id'] will be None. We force the
1672
False value in this case value because XML:RPC (communication between the server
1673
and the client) doesn't allow to transmit this value.
1675
.. i18n: store Parameter
1676
.. i18n: """""""""""""""
1677
.. i18n: It will calculate the field and store the result in the table. The field will be
1678
.. i18n: recalculated when certain fields are changed on other objects. It uses the
1679
.. i18n: following syntax:
1684
It will calculate the field and store the result in the table. The field will be
1685
recalculated when certain fields are changed on other objects. It uses the
1688
.. i18n: .. code-block:: python
1691
.. i18n: 'object_name': (
1692
.. i18n: function_name,
1693
.. i18n: ['field_name1', 'field_name2'],
1698
.. code-block:: python
1703
['field_name1', 'field_name2'],
1707
.. i18n: It will call function function_name when any changes are written to fields in the
1708
.. i18n: list ['field1','field2'] on object 'object_name'. The function should have the
1709
.. i18n: following signature::
1711
.. i18n: def function_name(self, cr, uid, ids, context=None):
1714
It will call function function_name when any changes are written to fields in the
1715
list ['field1','field2'] on object 'object_name'. The function should have the
1716
following signature::
1718
def function_name(self, cr, uid, ids, context=None):
1720
.. i18n: Where `ids` will be the ids of records in the other object's table that have
1721
.. i18n: changed values in the watched fields. The function should return a list of ids
1722
.. i18n: of records in its own table that should have the field recalculated. That list
1723
.. i18n: will be sent as a parameter for the main function of the field.
1726
Where `ids` will be the ids of records in the other object's table that have
1727
changed values in the watched fields. The function should return a list of ids
1728
of records in its own table that should have the field recalculated. That list
1729
will be sent as a parameter for the main function of the field.
1731
.. i18n: Here's an example from the membership module:
1734
Here's an example from the membership module:
1736
.. i18n: .. code-block:: python
1738
.. i18n: 'membership_state':
1739
.. i18n: fields.function(
1740
.. i18n: _membership_state,
1741
.. i18n: method=True,
1742
.. i18n: string='Current membership state',
1743
.. i18n: type='selection',
1744
.. i18n: selection=STATE,
1746
.. i18n: 'account.invoice': (_get_invoice_partner, ['state'], 10),
1747
.. i18n: 'membership.membership_line': (_get_partner_id,['state'], 10),
1748
.. i18n: 'res.partner': (
1749
.. i18n: lambda self, cr, uid, ids, c={}: ids,
1750
.. i18n: ['free_member'],
1755
.. code-block:: python
1761
string='Current membership state',
1765
'account.invoice': (_get_invoice_partner, ['state'], 10),
1766
'membership.membership_line': (_get_partner_id,['state'], 10),
1768
lambda self, cr, uid, ids, c={}: ids,
1773
.. i18n: Property Fields
1774
.. i18n: +++++++++++++++
1780
.. i18n: .. describe:: Declaring a property
1783
.. describe:: Declaring a property
1785
.. i18n: A property is a special field: fields.property.
1788
A property is a special field: fields.property.
1790
.. i18n: .. code-block:: python
1792
.. i18n: class res_partner(osv.osv):
1793
.. i18n: _name = "res.partner"
1794
.. i18n: _inherit = "res.partner"
1795
.. i18n: _columns = {
1796
.. i18n: 'property_product_pricelist':
1797
.. i18n: fields.property(
1798
.. i18n: 'product.pricelist',
1799
.. i18n: type='many2one',
1800
.. i18n: relation='product.pricelist',
1801
.. i18n: string="Sale Pricelist",
1802
.. i18n: method=True,
1803
.. i18n: view_load=True,
1804
.. i18n: group_name="Pricelists Properties"),
1808
.. code-block:: python
1810
class res_partner(osv.osv):
1811
_name = "res.partner"
1812
_inherit = "res.partner"
1814
'property_product_pricelist':
1816
'product.pricelist',
1818
relation='product.pricelist',
1819
string="Sale Pricelist",
1822
group_name="Pricelists Properties"),
1825
.. i18n: Then you have to create the default value in a .XML file for this property:
1828
Then you have to create the default value in a .XML file for this property:
1830
.. i18n: .. code-block:: xml
1832
.. i18n: <record model="ir.property" id="property_product_pricelist">
1833
.. i18n: <field name="name">property_product_pricelist</field>
1834
.. i18n: <field name="fields_id" search="[('model','=','res.partner'),
1835
.. i18n: ('name','=','property_product_pricelist')]"/>
1836
.. i18n: <field name="value" eval="'product.pricelist,'+str(list0)"/>
1842
<record model="ir.property" id="property_product_pricelist">
1843
<field name="name">property_product_pricelist</field>
1844
<field name="fields_id" search="[('model','=','res.partner'),
1845
('name','=','property_product_pricelist')]"/>
1846
<field name="value" eval="'product.pricelist,'+str(list0)"/>
1856
.. i18n: if the default value points to a resource from another module, you can use the ref function like this:
1858
.. i18n: <field name="value" eval="'product.pricelist,'+str(ref('module.data_id'))"/>
1863
if the default value points to a resource from another module, you can use the ref function like this:
1865
<field name="value" eval="'product.pricelist,'+str(ref('module.data_id'))"/>
1867
.. i18n: **Putting properties in forms**
1870
**Putting properties in forms**
1872
.. i18n: To add properties in forms, just put the <properties/> tag in your form. This will automatically add all properties fields that are related to this object. The system will add properties depending on your rights. (some people will be able to change a specific property, others won't).
1875
To add properties in forms, just put the <properties/> tag in your form. This will automatically add all properties fields that are related to this object. The system will add properties depending on your rights. (some people will be able to change a specific property, others won't).
1877
.. i18n: Properties are displayed by section, depending on the group_name attribute. (It is rendered in the client like a separator tag).
1880
Properties are displayed by section, depending on the group_name attribute. (It is rendered in the client like a separator tag).
1882
.. i18n: **How does this work ?**
1885
**How does this work ?**
1887
.. i18n: The fields.property class inherits from fields.function and overrides the read and write method. The type of this field is many2one, so in the form a property is represented like a many2one function.
1890
The fields.property class inherits from fields.function and overrides the read and write method. The type of this field is many2one, so in the form a property is represented like a many2one function.
1892
.. i18n: But the value of a property is stored in the ir.property class/table as a complete record. The stored value is a field of type reference (not many2one) because each property may point to a different object. If you edit properties values (from the administration menu), these are represented like a field of type reference.
1895
But the value of a property is stored in the ir.property class/table as a complete record. The stored value is a field of type reference (not many2one) because each property may point to a different object. If you edit properties values (from the administration menu), these are represented like a field of type reference.
1897
.. i18n: When you read a property, the program gives you the property attached to the instance of object you are reading. If this object has no value, the system will give you the default property.
1900
When you read a property, the program gives you the property attached to the instance of object you are reading. If this object has no value, the system will give you the default property.
1902
.. i18n: The definition of a property is stored in the ir.model.fields class like any other fields. In the definition of the property, you can add groups that are allowed to change to property.
1905
The definition of a property is stored in the ir.model.fields class like any other fields. In the definition of the property, you can add groups that are allowed to change to property.
1907
.. i18n: **Using properties or normal fields**
1910
**Using properties or normal fields**
1912
.. i18n: When you want to add a new feature, you will have to choose to implement it as a property or as normal field. Use a normal field when you inherit from an object and want to extend this object. Use a property when the new feature is not related to the object but to an external concept.
1915
When you want to add a new feature, you will have to choose to implement it as a property or as normal field. Use a normal field when you inherit from an object and want to extend this object. Use a property when the new feature is not related to the object but to an external concept.
1917
.. i18n: Here are a few tips to help you choose between a normal field or a property:
1920
Here are a few tips to help you choose between a normal field or a property:
1922
.. i18n: Normal fields extend the object, adding more features or data.
1925
Normal fields extend the object, adding more features or data.
1927
.. i18n: A property is a concept that is attached to an object and have special features:
1930
A property is a concept that is attached to an object and have special features:
1932
.. i18n: * Different value for the same property depending on the company
1933
.. i18n: * Rights management per field
1934
.. i18n: * It's a link between resources (many2one)
1937
* Different value for the same property depending on the company
1938
* Rights management per field
1939
* It's a link between resources (many2one)
1941
.. i18n: **Example 1: Account Receivable**
1944
**Example 1: Account Receivable**
1946
.. i18n: The default "Account Receivable" for a specific partner is implemented as a property because:
1949
The default "Account Receivable" for a specific partner is implemented as a property because:
1951
.. i18n: * This is a concept related to the account chart and not to the partner, so it is an account property that is visible on a partner form. Rights have to be managed on this fields for accountants, these are not the same rights that are applied to partner objects. So you have specific rights just for this field of the partner form: only accountants may change the account receivable of a partner.
1953
.. i18n: * This is a multi-company field: the same partner may have different account receivable values depending on the company the user belongs to. In a multi-company system, there is one account chart per company. The account receivable of a partner depends on the company it placed the sale order.
1955
.. i18n: * The default account receivable is the same for all partners and is configured from the general property menu (in administration).
1958
* This is a concept related to the account chart and not to the partner, so it is an account property that is visible on a partner form. Rights have to be managed on this fields for accountants, these are not the same rights that are applied to partner objects. So you have specific rights just for this field of the partner form: only accountants may change the account receivable of a partner.
1960
* This is a multi-company field: the same partner may have different account receivable values depending on the company the user belongs to. In a multi-company system, there is one account chart per company. The account receivable of a partner depends on the company it placed the sale order.
1962
* The default account receivable is the same for all partners and is configured from the general property menu (in administration).
1965
.. i18n: One interesting thing is that properties avoid "spaghetti" code. The account module depends on the partner (base) module. But you can install the partner (base) module without the accounting module. If you add a field that points to an account in the partner object, both objects will depend on each other. It's much more difficult to maintain and code (for instance, try to remove a table when both tables are pointing to each others.)
1969
One interesting thing is that properties avoid "spaghetti" code. The account module depends on the partner (base) module. But you can install the partner (base) module without the accounting module. If you add a field that points to an account in the partner object, both objects will depend on each other. It's much more difficult to maintain and code (for instance, try to remove a table when both tables are pointing to each others.)
1971
.. i18n: **Example 2: Product Times**
1974
**Example 2: Product Times**
1976
.. i18n: The product expiry module implements all delays related to products: removal date, product usetime, ... This module is very useful for food industries.
1979
The product expiry module implements all delays related to products: removal date, product usetime, ... This module is very useful for food industries.
1981
.. i18n: This module inherits from the product.product object and adds new fields to it:
1984
This module inherits from the product.product object and adds new fields to it:
1986
.. i18n: .. code-block:: python
1988
.. i18n: class product_product(osv.osv):
1990
.. i18n: _inherit = 'product.product'
1991
.. i18n: _name = 'product.product'
1992
.. i18n: _columns = {
1994
.. i18n: 'life_time': fields.integer('Product lifetime'),
1995
.. i18n: 'use_time': fields.integer('Product usetime'),
1996
.. i18n: 'removal_time': fields.integer('Product removal time'),
1997
.. i18n: 'alert_time': fields.integer('Product alert time'),
2000
.. i18n: product_product()
2003
.. code-block:: python
2005
class product_product(osv.osv):
2007
_inherit = 'product.product'
2008
_name = 'product.product'
2011
'life_time': fields.integer('Product lifetime'),
2012
'use_time': fields.integer('Product usetime'),
2013
'removal_time': fields.integer('Product removal time'),
2014
'alert_time': fields.integer('Product alert time'),
2024
.. i18n: This module adds simple fields to the product.product object. We did not use properties because:
2027
This module adds simple fields to the product.product object. We did not use properties because:
2029
.. i18n: * We extend a product, the life_time field is a concept related to a product, not to another object.
2030
.. i18n: * We do not need a right management per field, the different delays are managed by the same people that manage all products.
2033
* We extend a product, the life_time field is a concept related to a product, not to another object.
2034
* We do not need a right management per field, the different delays are managed by the same people that manage all products.
2036
.. i18n: ORM methods
2037
.. i18n: -----------
2043
.. i18n: Keeping the context in ORM methods
2044
.. i18n: ++++++++++++++++++++++++++++++++++
2047
Keeping the context in ORM methods
2048
++++++++++++++++++++++++++++++++++
2050
.. i18n: In OpenObject, the context holds very important data such as the language in
2051
.. i18n: which a document must be written, whether function field needs updating or not,
2055
In OpenObject, the context holds very important data such as the language in
2056
which a document must be written, whether function field needs updating or not,
2059
.. i18n: When calling an ORM method, you will probably already have a context - for
2060
.. i18n: example the framework will provide you with one as a parameter of almost
2061
.. i18n: every method.
2062
.. i18n: If you do have a context, it is very important that you always pass it through
2063
.. i18n: to every single method you call.
2066
When calling an ORM method, you will probably already have a context - for
2067
example the framework will provide you with one as a parameter of almost
2069
If you do have a context, it is very important that you always pass it through
2070
to every single method you call.
2072
.. i18n: This rule also applies to writing ORM methods. You should expect to receive a
2073
.. i18n: context as parameter, and always pass it through to every other method you call..
2076
This rule also applies to writing ORM methods. You should expect to receive a
2077
context as parameter, and always pass it through to every other method you call..
2079
.. i18n: ORM methods
2080
.. i18n: +++++++++++
2086
.. i18n: .. automodule:: openerp.osv.orm
2088
.. i18n: :show-inheritance:
2091
.. automodule:: openerp.osv.orm