Mappers are the ConnectorUnit classes responsible to transform external records into OpenERP records and conversely.
connector.unit.mapper.
ExportMapChild
(connector_env)[source]¶Bases: connector.unit.mapper.MapChild
MapChild
for the Exports
connector.unit.mapper.
ExportMapper
(connector_env)[source]¶Bases: connector.unit.mapper.Mapper
Mapper
for exports.
Transform a record from OpenERP to a backend record
connector.unit.mapper.
ImportMapChild
(connector_env)[source]¶Bases: connector.unit.mapper.MapChild
MapChild
for the Imports
format_items
(items_values)[source]¶Format the values of the items mapped from the child Mappers.
It can be overridden for instance to add the OpenERP
relationships commands (6, 0, [IDs])
, …
As instance, it can be modified to handle update of existing
items: check if an ‘id’ has been defined by
get_item_values()
then use the (1, ID, {values}
)
command
Parameters: | items_values (list) – list of values for the items to create |
---|
connector.unit.mapper.
ImportMapper
(connector_env)[source]¶Bases: connector.unit.mapper.Mapper
Mapper
for imports.
Transform a record from a backend to an OpenERP record
connector.unit.mapper.
MapChild
(connector_env)[source]¶Bases: connector.connector.ConnectorUnit
MapChild is responsible to convert items.
Items are sub-records of a main record.
In this example, the items are the records in lines
:
sales = {'name': 'SO10',
'lines': [{'product_id': 1, 'quantity': 2},
{'product_id': 2, 'quantity': 2}]}
A MapChild is always called from another Mapper
which
provides a children
configuration.
Considering the example above, the “main” Mapper
would
returns something as follows:
{'name': 'SO10',
'lines': [(0, 0, {'product_id': 11, 'quantity': 2}),
(0, 0, {'product_id': 12, 'quantity': 2})]}
A MapChild is responsible to:
Mapper
to convert the itemsskip_item()
)Mapper
(0, 0, {values})
A MapChild can be extended like any other
ConnectorUnit
.
However, it is not mandatory to explicitly create a MapChild for
each children mapping, the default one will be used
(ImportMapChild
or ExportMapChild
).
The implementation by default does not take care of the updates: if
I import a sales order 2 times, the lines will be duplicated. This
is not a problem as long as an importation should only support the
creation (typical for sales orders). It can be implemented on a
case-by-case basis by inheriting get_item_values()
and
format_items()
.
format_items
(items_values)[source]¶Format the values of the items mapped from the child Mappers.
It can be overridden for instance to add the OpenERP
relationships commands (6, 0, [IDs])
, …
As instance, it can be modified to handle update of existing
items: check if an ‘id’ has been defined by
get_item_values()
then use the (1, ID, {values}
)
command
Parameters: | items_values (list) – mapped values for the items |
---|
get_item_values
(map_record, to_attr, options)[source]¶Get the raw values from the child Mappers for the items.
It can be overridden for instance to:
Binder
to know if an
item already exists to modify an existing item, rather than to
add itParameters: |
---|
get_items
(items, parent, to_attr, options)[source]¶Returns the formatted output values of items from a main record
Parameters: |
|
---|---|
Returns: | formatted output values for the item |
connector.unit.mapper.
MapOptions
[source]¶Bases: dict
Container for the options of mappings.
Options can be accessed using attributes of the instance. When an option is accessed and does not exist, it returns None.
connector.unit.mapper.
MapRecord
(mapper, source, parent=None)[source]¶Bases: object
A record prepared to be converted using a Mapper
.
MapRecord instances are prepared by Mapper.map_record()
.
Usage:
mapper = SomeMapper(env)
map_record = mapper.map_record(record)
output_values = map_record.values()
See values()
for more information on the available arguments.
parent
¶Parent record if the current record is an item
source
¶Source record to be converted
update
(*args, **kwargs)[source]¶Force values to be applied after a mapping.
Usage:
mapper = SomeMapper(env)
map_record = mapper.map_record(record)
map_record.update(a=1)
output_values = map_record.values()
# output_values will at least contain {'a': 1}
The values assigned with update()
are in any case applied,
they have a greater priority than the mapping values.
values
(for_create=None, fields=None, **kwargs)[source]¶Build and returns the mapped values according to the options.
Usage:
mapper = SomeMapper(env)
map_record = mapper.map_record(record)
output_values = map_record.values()
When using the option for_create
, only the mappings decorated
with @only_create
will be mapped.
output_values = map_record.values(for_create=True)
When using the fields
argument, the mappings will be
filtered using either the source key in direct
arguments,
either the changed_by
arguments for the mapping methods.
output_values = map_record.values(fields=['name', 'street'])
Arbitrary key and values can be defined in the kwargs
arguments. They can later be used in the mapping methods
using self.options
.
output_values = map_record.values(tax_include=True)
Parameters: |
|
---|
connector.unit.mapper.
Mapper
(connector_env)[source]¶Bases: connector.connector.ConnectorUnit
A Mapper translates an external record to an OpenERP record and
conversely. The output of a Mapper is a dict
.
3 types of mappings are supported:
Example:
direct = [('source', 'target')]
Here, the source
field will be copied in the target
field.
A modifier can be used in the source item. The modifier will be applied to the source field before being copied in the target field. It should be a closure function respecting this idiom:
def a_function(field):
''' ``field`` is the name of the source field.
Naming the arg: ``field`` is required for the conversion'''
def modifier(self, record, to_attr):
''' self is the current Mapper,
record is the current record to map,
to_attr is the target field'''
return record[field]
return modifier
And used like that:
direct = [
(a_function('source'), 'target'),
]
A more concrete example of modifier:
def convert(field, conv_type):
''' Convert the source field to a defined ``conv_type``
(ex. str) before returning it'''
def modifier(self, record, to_attr):
value = record[field]
if not value:
return None
return conv_type(value)
return modifier
And used like that:
direct = [
(convert('myfield', float), 'target_field'),
]
More examples of modifiers:
A mapping method allows to execute arbitrary code and return one or many fields:
@mapping
def compute_state(self, record):
# compute some state, using the ``record`` or not
state = 'pending'
return {'state': state}
We can also specify that a mapping methods should be applied only when an object is created, and never applied on further updates:
@only_create
@mapping
def default_warehouse(self, record):
# get default warehouse
warehouse_id = ...
return {'warehouse_id': warehouse_id}
When a record contains sub-items, like the lines of a sales order, we can convert the children using another Mapper:
children = [('items', 'line_ids', 'model.name')]
It allows to create the sales order and all its lines with the
same call to openerp.models.BaseModel.create()
.
When using children
for items of a record, we need to create
a Mapper
for the model of the items, and optionally a
MapChild
.
Usage of a Mapper:
mapper = Mapper(env)
map_record = mapper.map_record(record)
values = map_record.values()
values = map_record.values(only_create=True)
values = map_record.values(fields=['name', 'street'])
children
= []¶direct
= []¶finalize
(map_record, values)[source]¶Called at the end of the mapping.
Can be used to modify the values before returning them, as the
on_change
.
Parameters: |
|
---|---|
Returns: | mapped values |
Return type: |
map_methods
¶Yield all the methods decorated with @mapping
map_record
(record, parent=None)[source]¶Get a MapRecord
with record, ready to be
converted using the current Mapper.
Parameters: |
|
---|
options
¶Options can be accessed in the mapping methods with
self.options
.
connector.unit.mapper.
MappingDefinition
(changed_by, only_create)¶Bases: tuple
changed_by
¶Alias for field number 0
only_create
¶Alias for field number 1
connector.unit.mapper.
MetaMapper
(name, bases, attrs)[source]¶Bases: connector.connector.MetaConnectorUnit
Metaclass for Mapper
Build a _map_methods
dict of mappings methods.
The keys of the dict are the method names.
The values of the dict are a namedtuple containing:
connector.unit.mapper.
backend_to_m2o
(field, binding=None)[source]¶A modifier intended to be used on the direct
mappings.
For a field from a backend which is an ID, search the corresponding binding in OpenERP and returns its ID.
When the field’s relation is not a binding (i.e. it does not point to
something like magento.*
), the binding model needs to be provided
in the binding
keyword argument.
Example:
direct = [(backend_to_m2o('country', binding='magento.res.country'),
'country_id'),
(backend_to_m2o('country'), 'magento_country_id')]
Parameters: |
|
---|
connector.unit.mapper.
changed_by
(*args)[source]¶Decorator for the mapping methods (mapping()
)
When fields are modified in OpenERP, we want to export only the modified fields. Using this decorator, we can specify which fields updates should trigger which mapping method.
If changed_by
is empty, the mapping is always active.
As far as possible, this decorator should be used for the exports, thus, when we do an update on only a small number of fields on a record, the size of the output record will be limited to only the fields really having to be exported.
Usage:
@changed_by('input_field')
@mapping
def any(self, record):
return {'output_field': record['input_field']}
Parameters: | *args – field names which trigger the mapping when modified |
---|
connector.unit.mapper.
convert
(field, conv_type)[source]¶A modifier intended to be used on the direct
mappings.
Convert a field’s value to a given type.
Example:
direct = [(convert('source', str), 'target')]
Parameters: |
|
---|
connector.unit.mapper.
follow_m2o_relations
(field)[source]¶A modifier intended to be used on direct
mappings.
‘Follows’ Many2one relations and return the final field value.
Assuming model is product.product
:
Parameters: | field – field “path”, using dots for relations as usual in Odoo |
---|
connector.unit.mapper.
m2o_to_backend
(field, binding=None)[source]¶A modifier intended to be used on the direct
mappings.
For a many2one, get the ID on the backend and returns it.
When the field’s relation is not a binding (i.e. it does not point to
something like magento.*
), the binding model needs to be provided
in the binding
keyword argument.
Example:
direct = [(m2o_to_backend('country_id', binding='magento.res.country'),
'country'),
(m2o_to_backend('magento_country_id'), 'country')]
Parameters: |
|
---|
connector.unit.mapper.
mapping
(func)[source]¶Declare that a method is a mapping method.
It is then used by the Mapper
to convert the records.
Usage:
@mapping
def any(self, record):
return {'output_field': record['input_field']}
connector.unit.mapper.
none
(field)[source]¶A modifier intended to be used on the direct
mappings.
Replace the False-ish values by None. It can be used in a pipeline of modifiers when .
Example:
direct = [(none('source'), 'target'),
(none(m2o_to_backend('rel_id'), 'rel_id')]
Parameters: |
|
---|