# Update data through browsable records

By default when updating values of a record, the change is automatically sent to the server. Let’s update the name of a partner:

    >>> Partner = odoo.env['res.partner']
    >>> partner = Partner.browse(1)
    >>> partner.name = "MyCompany"

This is equivalent to:

    >>> Partner.write([partner.id], {'name': "MyCompany"})

As one update is equivalent to one RPC query, if you need to update several fields for one record it is encouraged to use the write method as above

    >>> partner.write({'name': "MyCompany", 'website': 'http://example.net'})    # one RPC query

Or, deactivate the `auto_commit` option and commit the changes manually:

    >>> odoo.config['auto_commit'] = False
    >>> partner.name = "MyCompany"
    >>> partner.website = 'http://example.net'
    >>> partner.env.commit()    # one RPC by record modified

## Char, Float, Integer, Boolean, Text and Binary

As see above, it’s as simple as that:

    >>> partner.name = "New Name"

## Selection

Same as above, except there is a check about the value assigned. For instance, the field `type` of the `res.partner` model accept values contains in `['default', 'invoice', 'delivery', 'contact', 'other']`:

    >>> partner.type = 'default' # Ok
    >>> partner.type = 'foobar'  # Error!
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "odoorpc/service/model/fields.py", line 148, in __set__
        value = self.check_value(value)
      File "odoorpc/service/model/fields.py", line 160, in check_value
        field_name=self.name,
    ValueError: The value 'foobar' supplied doesn't match with the possible values '['default', 'invoice', 'delivery', 'contact', 'other']' for the 'type' field
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "odoorpc/service/model/fields.py", line 148, in __set__
        value = self.check_value(value)
      File "odoorpc/service/model/fields.py", line 160, in check_value
        field_name=self.name,
    ValueError: The value 'foobar' supplied doesn't match with the possible values '['default', 'invoice', 'delivery', 'contact', 'other']' for the 'type' field

## Many2one

You can also update a `many2one` field, with either an ID or a record:

    >>> partner.parent_id = 1                   # with an ID
    >>> partner.parent_id = Partner.browse(1)   # with a browsable record

You can’t put any ID or record, a check is made on the relationship to ensure data integrity:

    >>> User = odoo.env['res.users']
    >>> user = User.browse(1)
    >>> partner = Partner.browse(2)
    >>> partner.parent_id = user
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "odoorpc/service/model/fields.py", line 263, in __set__
        o_rel = self.check_value(o_rel)
      File "odoorpc/service/model/fields.py", line 275, in check_value
        field_name=self.name))
    ValueError: Instance of 'res.users' supplied doesn't match with the relation 'res.partner' of the 'parent_id' field.
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "odoorpc/service/model/fields.py", line 263, in __set__
        o_rel = self.check_value(o_rel)
      File "odoorpc/service/model/fields.py", line 275, in check_value
        field_name=self.name))
    ValueError: Instance of 'res.users' supplied doesn't match with the relation 'res.partner' of the 'parent_id' field.

## One2many and Many2many

`one2many` and `many2many` fields can be updated by providing a list of tuple as specified in the OpenERP/Odoo documentation, a list of records, a list of record IDs or an empty list or `False`:

With a tuple (as documented), no magic here:

    >>> user = odoo.env['res.users'].browse(1)
    >>> user.groups_id = [(6, 0, [8, 5, 6, 4])]

With a recordset:

    >>> groups = odoo.env['res.groups'].browse([8, 5, 6, 4])
    >>> user.groups_id = groups

With a list of record IDs:

    >>> user.groups_id = [8, 5, 6, 4]

The last two examples are equivalent to the first (they generate a `(6, 0, IDS)` tuple).

However, if you set an empty list or `False`, the relation between records will be removed:

    >>> user.groups_id = []
    >>> user.groups_id
    Recordset('res.group', [])
    >>> user.groups_id = False
    >>> user.groups_id
    Recordset('res.group', [])

Another facility provided by OdooRPC is adding and removing objects using Python operators `+=` and `-=`. As usual, you can add an ID, a record, or a list of them:

With a list of records:

    >>> groups = odoo.env['res.groups'].browse([4, 5])
    Recordset('res.group', [1, 2, 3])
    >>> user.groups_id += groups
    >>> user.groups_id
    Recordset('res.group', [1, 2, 3, 4, 5])

With a list of record IDs:

    >>> user.groups_id += [4, 5]
    >>> user.groups_id
    Recordset('res.group', [1, 2, 3, 4, 5])

With an ID only:

    >>> user.groups_id -= 4
    >>> user.groups_id
    Recordset('res.group', [1, 2, 3, 5])

With a record only:

    >>> group = odoo.env['res.groups'].browse(5)
    >>> user.groups_id -= group
    >>> user.groups_id
    Recordset('res.group', [1, 2, 3])

## Reference

To update a `reference` field, you have to use either a string or a browsable record as below:

    >>> IrActionServer = odoo.env['ir.actions.server']
    >>> action_server = IrActionServer.browse(7)
    >>> action_server.ref_object = 'res.partner,1'  # with a string with the format '{relation},{id}'
    >>> action_server.ref_object = Partner.browse(1)    # with a browsable record

A check is made on the relation name:

    >>> action_server.ref_object = 'foo.bar,42'
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "odoorpc/service/model/fields.py", line 370, in __set__
        value = self.check_value(value)
      File "odoorpc/service/model/fields.py", line 400, in check_value
        self._check_relation(relation)
      File "odoorpc/service/model/fields.py", line 381, in _check_relation
        field_name=self.name,
    ValueError: The value 'foo.bar' supplied doesn't match with the possible values '[...]' for the 'ref_object' field
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "odoorpc/service/model/fields.py", line 370, in __set__
        value = self.check_value(value)
      File "odoorpc/service/model/fields.py", line 400, in check_value
        self._check_relation(relation)
      File "odoorpc/service/model/fields.py", line 381, in _check_relation
        field_name=self.name,
    ValueError: The value 'foo.bar' supplied doesn't match with the possible values '[...]' for the 'ref_object' field

## Date and Datetime

`date` and `datetime` fields accept either string values or `datetime.date/datetime.datetime` objects.

With `datetime.date` and `datetime.datetime` objects:

    >>> import datetime
    >>> Purchase = odoo.env['purchase.order']
    >>> order = Purchase.browse(1)
    >>> order.date_order = datetime.date(2011, 9, 20)
    >>> order.minimum_planned_date = datetime.datetime(2011, 9, 20, 12, 31, 24)

With formated strings:

    >>> order.date_order = "2011-09-20"                     # %Y-%m-%d
    >>> order.minimum_planned_date = "2011-09-20 12:31:24"  # %Y-%m-%d %H:%M:%S

As always, a wrong type will raise an exception:

    >>> order.date_order = "foobar"
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "odoorpc/fields.py", line 187, in setter
        value = self.check_value(value)
      File "odoorpc/fields.py", line 203, in check_value
        self.pattern))
    ValueError: Value not well formatted, expecting '%Y-%m-%d' format
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "odoorpc/fields.py", line 187, in setter
        value = self.check_value(value)
      File "odoorpc/fields.py", line 203, in check_value
        self.pattern))
    ValueError: Value not well formatted, expecting '%Y-%m-%d' format

Next step: Download reports