Creating Records
create() function is used to create new records for a particular model. The new records
are initialized using the values from the list of dicts vals_list, and, if necessary,
those from the default_get() function.
Parameters
Values for the model’s fields, as a list of dictionaries:
[{'field_name': field_value, ...}, ...]
Eg:
partner = self.env['res.partner'].create({
'name':'Test Partner',
'is_company':True
})
It will raise an AccessError
- If the user has no create access on the requested object
- If the user tries to bypass access rules for creat on the requested object
It will raise ValidationError
- If the user tries to enter an invalid value for a field that is not in selection
It will raise UserError
- If a loop would be created in a hierarchy of objects a result of the operation (such
as setting an object as its own parent)
Updating Records
Sometimes it’ll be required to update records by changing the values of some of their
fields.
We can use the update() method of a model for this.
There are three ways to assign a particular field value to a record.
1. Assigning values directly to the attribute representing the
field of the record.
- We can assign a value to a field directly.
self.test_boolean = True
self is the object of the record of which record’s field value is updating.test_boolean
is a boolean field.
2.update() method
- We can use the update() method to update the value of a field.
self.update({
'start_date': fields.Date.today(),
'test_boolean': True
})
start date and test_boolean is the field which we need to update. We can pass a
dictionary that maps the field names to the values you want to set to the update method.
3.write() method
- We can pass a dictionary that maps the field names to the values you want to set to the
update method
self.write({
'start_date': fields.Date.today(),
'test_boolean': True
})
- This method works for recordsets of arbitrary size and will update all records with the
specified values in one single database operation when the two previous options perform
one database call per record and per field. However, it has some limitations: it does
not work if the records are not yet present in the database. Also, it requires a special
format when writing relational fields, similar to the one used by the create() method.
(0, 0, { values }) link to a new record that needs to be created with the given values
dictionary.
(1, ID, { values }) update the linked record with id = ID (write values on it).
(2, ID) remove and delete the linked record with id = ID (calls unlink on ID, that will
delete the object completely and the link to it as well).
(3, ID) cut the link to the linked record with id = ID (delete the relationship between
the two objects but do not delete the target object itself).
(4, ID) link to existing record with id = ID (adds a relationship).
(5) unlink all (like using (3, ID) for all linked records).
(6, 0, [IDs]) replace the list of linked IDs (like using (5) then (4, ID) for each ID in
the list of IDs).
Searching Records
Searching records based on some conditions are necessary for business logic methods. In
Odoo, we can use search() method to do so.
Let’s take an example; in this example, we are searching those partners whose
‘company_type’ is ‘company’
domain = [('company_type','=','company')]
partner = self.env['res.partner'].search(domain)
>>>res.partner(1,2,3,6,9,10,13,15,16,17)
The search method with the domain will return the recordest. A domain is a list of
criteria, each criterion being a triple (either a list or a tuple) of (field_name,
operator, value).
● field_name (str)
A field name of the current model, or a relationship traversal through a Many2one
using dot-notation, e.g. 'street' or 'partner_id.country'
● operator (str)
an operator used to compare the field_name with the value. Valid operators are:
= equals to
!=not equals to
>greater than
>=greater than or equal to
< less than
<= less than or equal to
=? unset or equals to (returns true if value is
either None or False, otherwise behaves like =)
=like - matches field_name against the value pattern. An underscore _ in the pattern
stands for (matches) any single character; a percent sign % matches any string of
zero or more characters.
like - matches field_name against the %value% pattern. Similar to =like but wraps
value with ‘%’ before matching.
not like - it doesn’t match against the %value% pattern.
ilike - case insensitive like.
not ilike - case insensitive not like.
=ilike - case insensitive =like.
not in-is unequal to all of the items from value.
child_of-Is a child (descendant) of a value record (value can be either one item or
a list of items).
Takes the semantics of the model into account (i.e., following the relationship field
named by _parent_name).
parent_of - Is a parent (ascendant) of a value record (value can be either one item
or a list of items).
Takes the semantics of the model into account (i.e., following the relationship field
named by _parent_name).
value
Variable type must be comparable to the named field with the operator.
Domain criteria can be combined using logical operators in prefix form:
'&' - logical AND
'|'- logical OR
'!'- logical NOT
Note:
Mostly to negate combinations of criteria. Individual criterion generally have a negative
form (e.g., = -> !=, < -> >=) which is simpler than negating the positive.
Example:
To search for partners named ABC, from Belgium or Germany, whose language is not English:
[('name','=','ABC'),
('language.code','!=','en_US'),
'|',('country_id.code','=','be'),
('country_id.code','=','de')]
This domain is interpreted as:
(name is 'ABC')
AND (language is NOT english)
AND (country is Belgium OR Germany)
The other keyword arguments that matches in the search method.
•offset=N: This is used to skip the first N records that match the
query. Its default is 0.
• limit=N: This indicates that N records will be returned. By default,
there is no limit.
• order=sort_specification: By default, the order is the _order
attribute of the model class.
• count=boolean : If True, it will return the number of records in the
recordset.The default is False
Note:
The search() method with the count attribute and search_count() function both gives the
same result.
Combining Recordset
Sometimes, we will get a recordset that is not what we need.
1. To merge two recordsets into one while preserving their order:result = recordset1 +
recordset2
2. To merge two recordsets into one by ensuring that there are no duplicates in the
result:result = recordset1 | recordset
3. To find the records that are common in two recordsets: result = recordset1 &
recordset2.
Some of the common python operators that can be used in combining recordsets:
-R1+R2: This will return a combination of the two recordsets, the
records from R1 followed by the records from R2. The new recordset may have
duplicate records
-R1-R2: This will return a new recordset that will have records from
R1 that are not in R2. The order is preserved.
-R1&R2: This will perform the intersection of the two recordsets.
It will contain the records from both R1 and R2 but no duplicates. The order is not
preserved.
-R1 | R2: This will perform the union of the two recordsets. This
will return a new recordset with records from either R1 or R2. There are no
duplicate records. The order is not preserved.
-R1==R2: It will return True if both the recordsets R1 and R2 have
the same records.
-R1<=R2: True if all records in R1 are a subset of R2.
-R1< R2: True if all records in R1 are a subset of R2.
-R1>=R2: True if all the records in R2 are a
subset of R1.
-R1 !=R2: True if both the recordset have no same records.
-R1 in R2: True if R2 contains R1.R1 should be one record
-R1 not in R2: True if R2 doesn’t contain R1.R1 should be one
record.
Filtering Records
Sometimes, if we already have a recordset and need a subset of the recordset based on
some conditions, we will filter out the corresponding records from the recordset, we use
filtered() method for this.
A function or a dot-separated sequence of field names can be passed as a parameter to the
filtered() function. It will return the records satisfying the condition, which may be
empty.
# only keep records whose company is the current user's
records.filtered(lambda r: r.company_id == user.company_id)
# only keep records whose partner is a company
records.filtered("partner_id.is_company")
Sorting Records
The sorted() method can be used to sort a recordset.
- If the recordset is obtained by a search() method, the order attribute can be used
in the method to sort the returned recordset.
partner = self.env['res.partner'].search([(),order='id'])
This will return all the partners which are sorted in ascending order of records
‘id’.
_order attribute of the model can also be used to sort the records of the model
sorted() method can be used to sort a recordset
partners = self.env['res.partner'].search([('company_type','=','company')])
partners.sorted(key='id')
Internally, the sorted() method will fetch the data of the field that's passed as the
key argument. Then, by using Python's native sorted method, it returns a sorted
recordset.
It also has one optional argument, reverse=True , which returns a recordset in
reverse order.
partners = self.env['res.partner'].search([('company_type','=','company')])
partners.sorted(key='id', reverse=True)