merge
This commit is contained in:
commit
be9ace6ba7
1 file changed
+255
-54
+255
-54
@@ -8,22 +8,51 @@ which provide the framework integration like the database abstraction,
|
||||
worklows, translations, etc.
|
||||
|
||||
|
||||
The following snippet gives a minimal example:
|
||||
The following snippet gives a first example:
|
||||
|
||||
.. highlight:: python
|
||||
|
||||
::
|
||||
|
||||
class Category(OSV):
|
||||
"Party category"
|
||||
_name = 'relationship.category'
|
||||
_description = __doc__
|
||||
name = fields.Char('Name')
|
||||
Category()
|
||||
|
||||
class Country(OSV):
|
||||
"Country"
|
||||
_name = 'relationship.country'
|
||||
_description = __doc__
|
||||
name = fields.Char('Name')
|
||||
Category()
|
||||
|
||||
class Address(OSV):
|
||||
"Address"
|
||||
_name = 'relationship.address'
|
||||
_description = __doc__
|
||||
name = fields.Char('Contact Name')
|
||||
party = fields.Many2One('relationship.party', 'Party')
|
||||
country = fields.Many2One('relationship.country', 'Country')
|
||||
city = fields.Char('City')
|
||||
Address()
|
||||
|
||||
class Party(OSV):
|
||||
"Party"
|
||||
_description = __doc__
|
||||
_name = "relationship.party"
|
||||
name = fields.Char('Name')
|
||||
addresses = fields.One2Many('relationship.address', 'party', 'Addresses')
|
||||
categories = fields.Many2Many('relationship.category', 'relationship_category_rel',
|
||||
'party', 'category', 'Categories')
|
||||
Party()
|
||||
|
||||
Instanciating the class make it alive for the framework. Actually
|
||||
there will be only one instance per class and per database. So model
|
||||
classes are essentially accessors to the underlying table.
|
||||
instances are essentially accessors to the underlying table. Columns of
|
||||
the table correspond to the fields of the class. Rows of the table
|
||||
corresponds to records.
|
||||
|
||||
|
||||
Model Properties
|
||||
@@ -32,32 +61,29 @@ Model Properties
|
||||
Model properties defines meta-informations about the model, they are
|
||||
class attributes starting with and underscore.
|
||||
|
||||
* ``_description``: A non technical description of the class.
|
||||
* ``_description``: A non technical description of the model.
|
||||
|
||||
* ``_name``: The unique identifier that can be use to reference the
|
||||
class across all the framwork. The first part of it must be the
|
||||
name in which the class is defined.
|
||||
model across all the framwork. The first part of it (before the
|
||||
dot) must be the name of the module in which the class is
|
||||
defined.
|
||||
|
||||
* ``_table``: The name of the database table which is mapped to
|
||||
the current class. If not set the value of ``_name`` is used with
|
||||
dots converted to underscores.
|
||||
|
||||
* ``_rec_name``: The name of the main field of the class. If not
|
||||
* ``_rec_name``: The name of the main field of the model. If not
|
||||
set the field ``name`` is used (like in the above example).
|
||||
|
||||
* ``_sequence``: The name of the postgresql sequence that
|
||||
increment the ``id`` column.
|
||||
|
||||
|
||||
* ``_order_name``: The name of the field on which the row must
|
||||
be sorted when the underlying table is read.
|
||||
|
||||
* ``_order_name``: The name of the field (or an sql expression) on
|
||||
which the row must be sorted when the underlying table is read.
|
||||
|
||||
* ``_auto``: When set to ``False`` will prevent the framework from
|
||||
creating a table for this class.
|
||||
|
||||
* ``_obj``: (?)
|
||||
|
||||
* ``_sql``: The sql code that must be used to fetch data from the
|
||||
database. The columns outputed by the given query must reflect
|
||||
the class fields.
|
||||
@@ -73,13 +99,6 @@ them at other places in the framework
|
||||
message. E.g.: ``{'recursive_categories': 'You can not create
|
||||
recursive categories!'}``
|
||||
|
||||
* ``_sql_constraints``: A list of constraints that are added on
|
||||
the underlying table. E.g.: ``('constrain_name, sql_constraint,
|
||||
'error_msg')`` where ``'constrain_name'`` is the name of the
|
||||
sql constraint for the database, ``sql_constraint`` is the actual
|
||||
sql constraint (E.g.: ``'UNIQUE(name)'``) and ``'error_msg'`` is
|
||||
one of the key of ``_error_messages``.
|
||||
|
||||
* ``_constraints``: A list of constraints that each record must
|
||||
respect. Each item of this list is a couple ``('function_name',
|
||||
'error_keyword')``, where ``'function_name'`` is the name of a
|
||||
@@ -87,18 +106,39 @@ them at other places in the framework
|
||||
(``False`` when the constraint is violated). ``error_keyword``
|
||||
must be one of the key of ``_sql_error_messages``.
|
||||
|
||||
* ``_sql_error_messages``:
|
||||
* ``_sql_constraints``: A list of constraints that are added on
|
||||
the underlying table. E.g.: ``('constrain_name, sql_constraint,
|
||||
'error_msg')`` where ``'constrain_name'`` is the name of the
|
||||
sql constraint for the database, ``sql_constraint`` is the actual
|
||||
sql constraint (E.g.: ``'UNIQUE(name)'``) and ``'error_msg'`` is
|
||||
one of the key of ``_error_messages``.
|
||||
|
||||
* ``_rpc_allowed``: The list of the names of the method than are
|
||||
allowed to be called remotely.
|
||||
* ``_sql_error_messages``: Like ``_error_messages`` for
|
||||
``_sql_constraints``.
|
||||
|
||||
* ``_rpc_allowed``: The list of the names of the method that are
|
||||
allowed to be called remotely. By default it contains: ``[
|
||||
'read', 'write', 'create', 'default_get', 'delete', 'fields_get',
|
||||
'fields_view_get', 'search', 'name_get', 'name_search', 'copy',
|
||||
'import_data', 'export_data', 'search_count', 'search_read']``
|
||||
|
||||
|
||||
Fields
|
||||
******
|
||||
|
||||
Fields are class attributes that do not start with an underscore. Some
|
||||
fields are automatically added on each tables: id, create_date,
|
||||
create_uid, write_date, write_uid. (TODO)
|
||||
fields are automatically added on each tables:
|
||||
|
||||
* ``id``: An integer providing a identifier for each row.
|
||||
|
||||
* ``create_date``: The date at which the row was added.
|
||||
|
||||
* ``create_uid``: The identifier of the user (I.e. the ``id`` of
|
||||
one row of the table defining the users) who created the row.
|
||||
|
||||
* ``write_date``: The date of the last modification.
|
||||
|
||||
* ``write_uid``: The user who made the last modification.
|
||||
|
||||
|
||||
Fields types
|
||||
@@ -138,42 +178,106 @@ Or one of these composed types:
|
||||
|
||||
Or one of these relation types:
|
||||
|
||||
* ``Many2One``:
|
||||
|
||||
* ``One2Many``:
|
||||
|
||||
* ``Many2Many``:
|
||||
|
||||
Fields options
|
||||
^^^^^^^^^^^^^^
|
||||
|
||||
This options are avalaible on several types of fields:
|
||||
|
||||
* ``readonly``
|
||||
|
||||
* ``required``
|
||||
|
||||
* ``help``
|
||||
|
||||
* ``select``
|
||||
|
||||
* ``on_change``
|
||||
|
||||
* ``states``
|
||||
|
||||
* ``domain``
|
||||
|
||||
* ``translate``
|
||||
|
||||
|
||||
Other options:
|
||||
* ``Many2One``: A relation from the current model to another one
|
||||
where several record of the current model can be linked to the
|
||||
same record of the other. E.g.: ``party =
|
||||
fields.Many2One('relationship.party', 'Party')`` where
|
||||
``'relationship.party'`` is the identifier of the other
|
||||
model. This correspond in the database to a foreign key from the
|
||||
table of the current model to the ``relationship_party`` table.
|
||||
|
||||
* ``One2Many``: A relation from the current model to another one
|
||||
where one record of the current model can be linked to many
|
||||
records of the other. E.g.: ``addresses =
|
||||
fields.One2Many('relationship.party', 'party',
|
||||
'Addresses')``. This correspond in the database to a foreign key
|
||||
(who's name is ``party``) from the ``relationship_address`` table
|
||||
to the table of the current model.
|
||||
|
||||
* ``Many2Many``: A relation from the current model to another one
|
||||
where many record of the current model can be linked to many
|
||||
records of the other. E.g.: ``categories =
|
||||
fields.Many2Many('relationship.category',
|
||||
'relationship_category_rel', 'party', 'category',
|
||||
'Categories')``. This correspond in the database to a new table
|
||||
``relationship_category_rel`` with two foreing key ``party`` and
|
||||
``category`` pointing to ``relationship_party`` and
|
||||
``relationship_category``.
|
||||
|
||||
|
||||
Function field can be used to mimic any other type:
|
||||
|
||||
* ``Function``:
|
||||
* ``Function``: A computed field. E.g. ``total =
|
||||
fields.Function('get_total', type='float',
|
||||
string='Total')``. Where ``'get_total'`` is the name if a method
|
||||
of the current class.
|
||||
|
||||
|
||||
Fields options
|
||||
^^^^^^^^^^^^^^
|
||||
|
||||
Options are available on all type of fields, except when stated
|
||||
otherwise in the desctiption.
|
||||
|
||||
* ``readonly``: A boolean, when set to ``True`` the field is not
|
||||
editable in the interface.
|
||||
|
||||
* ``required``: A boolean. When a field is required a ``NOT NULL``
|
||||
constraint is added in the database. It appear with a blue
|
||||
background in the interface.
|
||||
|
||||
* ``help``: A text to be show in the interface on mouse-over.
|
||||
|
||||
* ``select``: A boolean. When equel to ``True``, an index is
|
||||
created in the database and the field appear in the search box on
|
||||
list view.
|
||||
|
||||
* ``on_change``: The name of a method the the client must call when
|
||||
a user change the field. This method must return a distionnary
|
||||
``{field_name: new_value}`` for all the field that must be updated.
|
||||
|
||||
* ``states``: A dictionnary. Keys are name of other options and
|
||||
values are python expression. This allow to update dynamically
|
||||
options for the current field. E.g.: ``states={"readonly":
|
||||
"total > 10"}``.
|
||||
|
||||
* ``domain``: A domain on the current field. E.g.: ``['name', '!=',
|
||||
'Steve']`` on the ``party`` field of the ``relationship.address``
|
||||
model will forbid to link the current address to a Party for
|
||||
which ``name`` is equal to ``Steve``
|
||||
|
||||
* ``translate``: If true, this field is translatable. A flag in the
|
||||
interface will allow users to change translate the field for
|
||||
their language.
|
||||
|
||||
* ``priority``: An integer. Allow to force the order in which
|
||||
fields are writen in the database. This is used only for fields
|
||||
that are not in the table, like One2Many.
|
||||
|
||||
* ``change_default``: When the user choose a default value for a
|
||||
field in the current model, the current field with
|
||||
``change_default`` equal to ``True`` can be used as a a condition
|
||||
to the default value.
|
||||
|
||||
* ``on_change_with``: Like onchange, but is be defined the other
|
||||
way around: It's a list containing all the fields than must
|
||||
update the current field.
|
||||
|
||||
* ``size``: A maximum size on ``Char`` fields.
|
||||
|
||||
* ``digits``: A couple of integer which define the total number of
|
||||
digit and the number of decimal to show in the interface. Only
|
||||
for ``Float`` and ``Numeric``.
|
||||
|
||||
* ``on_delete``: Sql expression handling behaviour when a the
|
||||
target of a ``Many2One`` is removed. Possible values:
|
||||
``CASCADE``, ``DO NOTHING``, ``SET NULL`` (default).
|
||||
|
||||
* ``context``: A string defining a dictionnay which will be given
|
||||
to evaluate the field.
|
||||
|
||||
* ``ondelete_origin`` and ``ondelete_target``: Like ``on_delete``
|
||||
for the column of the table supporting a ``Many2Many`` relation.
|
||||
|
||||
|
||||
|
||||
@@ -183,18 +287,115 @@ Manipulating Models
|
||||
Create
|
||||
******
|
||||
|
||||
Signature:
|
||||
|
||||
.. highlight:: python
|
||||
|
||||
::
|
||||
|
||||
def create(self, cursor, user, vals, context=None):
|
||||
|
||||
|
||||
Where:
|
||||
* ``self``: The current model on which the action take place.
|
||||
|
||||
* ``cursor``: An instance of the ``Fakecursor`` class.
|
||||
|
||||
* ``user``: The id of the user initiating the action.
|
||||
|
||||
* ``vals``: A dictionnary containing the values to be writen in
|
||||
the database.
|
||||
|
||||
* ``context``: The context of the action.
|
||||
|
||||
Return: The id of the new record.
|
||||
|
||||
Read
|
||||
****
|
||||
|
||||
Signature:
|
||||
|
||||
.. highlight:: python
|
||||
|
||||
::
|
||||
|
||||
def read(self, cursor, user, ids, fields_names=None, context=None)
|
||||
|
||||
Where:
|
||||
|
||||
* ``self``: The current model on which the action take place.
|
||||
|
||||
* ``cursor``: An instance of the ``Fakecursor`` class.
|
||||
|
||||
* ``ids``: A list of integer defining the rows to be read.
|
||||
|
||||
* ``user``: The id of the user initiating the action.
|
||||
|
||||
* ``fields_name``: A list of the name of the columns to be
|
||||
read. If empty all the columns a read.
|
||||
|
||||
* ``context``: The context of the action.
|
||||
|
||||
Return: a list of dictionnary whose keys are the fields names.
|
||||
|
||||
Note: one should favor ``browse`` over ``read``, because it's more
|
||||
powerful.
|
||||
|
||||
Browse
|
||||
******
|
||||
|
||||
Signature:
|
||||
|
||||
.. highlight:: python
|
||||
|
||||
::
|
||||
|
||||
def browse(self, cursor, user, ids, context=None):
|
||||
|
||||
Where:
|
||||
|
||||
* ``self``: The current model on which the action take place.
|
||||
|
||||
* ``cursor``: An instance of the ``Fakecursor`` class.
|
||||
|
||||
* ``ids``: A list of integer defining the rows to be read.
|
||||
|
||||
* ``user``: The id of the user initiating the action.
|
||||
|
||||
* ``context``: The context of the action.
|
||||
|
||||
Return: A ``BrowseRecordList`` instance.
|
||||
|
||||
Example usage:
|
||||
|
||||
.. highlight:: python
|
||||
|
||||
::
|
||||
|
||||
party_obj = self.pool.get('relationship.party')
|
||||
parties = party_obj.browse(self, cursor, user, ids, context=None)
|
||||
countries = Set()
|
||||
for party in parties:
|
||||
for address in party.addresses:
|
||||
countries.add(party.country.name)
|
||||
|
||||
|
||||
This example collect all the countries connected to a given set of
|
||||
parties (defined by ``ids``).
|
||||
|
||||
One can see that the ``BrowseRecord`` list return by the ``browse`` function
|
||||
is able to resolve foreign keys by itself and thus allowing to browse
|
||||
the data in a pythonic way.
|
||||
|
||||
Write
|
||||
*****
|
||||
|
||||
Delete
|
||||
******
|
||||
|
||||
Search
|
||||
******
|
||||
|
||||
inheritance
|
||||
###########
|
||||
|
||||
Reference in new issue
Block a user