XML Files
In Odoo, data records can be defined using XML files. XML files will be used to
store the data. First, we must build a directory named data within the module. Data.xml
files are frequently created under the directory data. Let's look at how to construct
partner data with XML files. To do this, let us construct a new module named custom_contacts,
which will contain a new directory called data. Create an XML file called res_partner_data.xml
in the data directory. The record data may be loaded using an XML file by following
the syntax below.
<record model="model.name" id="record_id">
<field name="field_name">field_data </field>
</record>
To create a record, all mandatory fields must be filled out. Using the XML code
shown below, we can construct a partner record. The record tag is used to make the
record. The record tag can have two attribute values: id and model. 'Id' is the
XML record's unique identifier. The 'Model' parameter indicates the model in which
the record is being generated. We are creating a new record in the Contacts model
in this example, the model is specified as res.partner. Each field value is specified
within the record using the field tag shown below. The Name defines the field's
technical name, and after that, the field value is given.
<odoo>
<data>
<record id="partner_1" model="res.partner">
<field name="name">Aby Wills</field>
<field name="phone">9865432344</field>
<field name="email">aby@example.com</field>
</record>
</data>
</odoo>
After making the data.xml file, add it in the __manifest__.py file as shown below.
'data' : [
'data/res_partner_data.xml'
]
Install the custom_contacts module after you've configured it. After installing
the module, a partner data with the specified values will be created in the database.
CSV Files
When importing significant amounts of data, CSV files are needed since XML files
may not be sufficient. CSV files are used in Odoo source modules. They are mostly
used to define access rights. When working with CSV files, There are some important
points to remember.
- The name of this file should be model_name.csv, "ir.model.access.csv," for example.
The model name for the access rights is ir.model.access.CSV files are also included
within the manifest.
- The fields that need to be written into will be listed in the first row of the CSV
file, along with a field id for the external ID (used for creation or updating).
Let's look at this with an example. Consider the account.tax.group.csv file for
this.
id,name,country_id/id
tax_group_0,TVA 0%,base.lu
tax_group_3,TVA 3%,base.lu
tax_group_6,TVA 6%,base.lu
tax_group_8,TVA 8%,base.lu
tax_group_10,TVA 10%,base.lu
tax_group_12,TVA 12%,base.lu
tax_group_14,TVA 14%,base.lu
tax_group_15,TVA 15%,base.lu
tax_group_17,TVA 17%,base.lu
The first row defines the fields, which are then followed by values. As a result,
when you install the module that includes this CSV file, the relevant records in
the model account.tax.group will be created.
No Update
In Odoo, the
tag has an attribute called No Update. When a module is updating, this parameter
is used to indicate that the values in the XML file need to be recreated. The contents
of data files may only be applied once in certain situations. We can set the noupdate
attribute to 1 at that point. Here is an example of a noupdate:
<odoo>
<data noupdate="1">
<record id="res_partner_data" model="res.partner">
<field name="name">Demo Partner</field>
<field name="email">demo@gmail.com</field>
</record>
</data>
</odoo>
In the model res.partner, a partner Demo Partner is created during module installation.
During the module update, any modifications we created for the record will not have
an impact. This means that in the code above, the email and name will remain unchanged
even if we change it and upgrade the module.
Force Create
Similar to 'noupdate,' the 'forcecreate' is also an attribute of the tag. When you
use this attribute, you ensure that the record is created if it doesn't already
exist. The 'forcecreate' attribute is true on by default. This also needs an external
ID for the record to make this work. Let's look at an example for better understanding:
<record forcecreate="True" id="decimal_payment" model="decimal.precision">
<field name="name">Payment Terms</field>
<field name="digits">6</field>
</record>
Here, if there is no record found in the model decimal.precision with external id
decimal_payment, a new record will be created.
External IDs
An External ID is basically a special name that helps identify a particular record
in an XML file. They are also called as XML IDs.These are records of the model ir.model.data
which are imported in the case of importing data in Odoo.
When we are importing data using XML IDs, it initially checks for the existence
of a record with the same identifier. If there is an existing record with the XML
ID, then the UPDATE process will be worked. Otherwise, the CREATE operation will
be processed. Usually, XML IDs will be the combination of the record ID and the
module name.
E.g., sale.mail_act_sale_upsell
We can update any XML record if the external ID is known. Consider the below as
an example.
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data noupdate="1">
<record id="base.main_company" model="res.company">
<field name="name">My Company (San Francisco)</field>
</record>
</data>
</odoo>
Here the ID of the record is given as XML ID of the main company.Since there is
a record with this XML ID, update operation will be performed, resulting in the
name changing of the main company.The name field value will be updated to “My Company
(San Francisco). There is an option to get the External ID of any records from the
User Interface. After enabling debug mode, the developer tool menu will be shown.
There is an option to see the metadata of the record from here. External ID is shown
inside the metadata.
Namespaces
In Odoo, namespaced phrases refer to external IDs that contain exactly one dot (.).
Namespacing is a way to organize and uniquely identify records, and it helps prevent
naming conflicts between different modules. When using the external ID for a record
tag, Odoo first checks if it is namespaced. That is, if it contains exactly one
dot. If it is not namespaced, then Odoo adds the module name as the namespace for
the record. Here's an example of namespaced phrases for an external ID:
<record id="module_name.external_id" model="ir.model.data">
<field name="name">module_name.external_id</field>
<field name="model">your.model</field>
<field name="res_id">your_record_id</field>
</record>
In this example:
- module_name is the namespace.
- external_id is the specific name or identifier for the record within that
namespace.
When Odoo encounters an external ID like module_name.external_id, it understands
that module_name is the module providing this record. If you don't provide a namespace
(i.e., if the external ID doesn't contain a dot), Odoo assumes the record belongs
to the current module, and it automatically adds the module name as the namespace.
Delete Data from XML
Let’s delve into the details of how to delete records from XML in Odoo. When working
with Odoo, you might encounter scenarios where you need to remove previously created
records during module installation. The <delete> tag comes in handy for this
purpose. There are two methods to achieve this:
- Using XML ID
- Using Search Domain
Using XML ID
In this method, you specify the XML ID of the records you want to delete.
The syntax is as follows:
<delete model="your model name" id="XML ID of the record"/>
Here:
- your_model_name refers to the model where the record exists,
- XML_ID_of_the_record is the unique identifier assigned to the record during its
creation from another module’s data files.
Odoo will search for the record using the provided XML ID. If found, it will delete
the corresponding record. If no matching record is found, an error will be raised.
Note that you can only delete records created from XML files (those with XML IDs).
<record id="demo_category_1" model="product.category">
<field name="name">Category 1</field>
</record>
For example, to delete this record, you have to follow the steps below.
<delete model = "product.category" id = "demo_category_1"/>
Using Search Domain
In this method, you define a search domain to identify records for deletion. Specify
the domain using the domain attribute. During module installation, Odoo will search
for records based on the given domain. If matching records are found, they will
be deleted. Unlike the first method, this approach won’t raise an error if no records
match the specified domain. However, be cautious, as it can delete user data. The
syntax is as follows:
<delete model = "model_name" search="domain"/>
Let us discuss the syntax with an example.
<delete model = "sale.order" search='[(partner_id.name,'=','Azure Interior')]'/>
By executing the provided code, Odoo will remove all Sale Orders associated with
the partner named Azure Interior. Commonly delete is rarely used in Odoo.
Function call from XML
Once a module is installed, you may be required to perform certain functions or
methods. Odoo allows you to call a function from XML. The
tag is used to execute Python functions directly from XML. There are two methods
for calling a function from XML.
- Invoking function without parametersInvoking function without parameters
- Invoking function with parameters
Invoking function without parameters
We can use this method to call a function defined within any model without passing
any parameters. The syntax is provided below
<function id="function_id" model="model_name" name="method_name"/>
The model of the method is specified in the function tag's attribute model. Other
attributes include id and name. The id specifies the XML record's unique identifier,
and the name corresponds to the method name.
Let's look at a function call without parameters.
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data noupdate="1">
<function id="func_call_without_params" model="product.product" name="func_without_params"/>
</data>
</odoo>
The model in this case is product.product. As a result, the system will call the
method func_call_without_params, which is defined in the model product.product.
As a result, the method definition will be as follows.
from odoo import api, fields, models
class product(models.Model):
_inherit = "product.product"
@api.model
def func_without_params(self):
self.create(dict(name='Test'))
After including the XML data file in the manifest, the method will be called when
the module is installed, and a new record will be created in the model product.product.
Invoking function with parameters
The following method is to call a function with parameters. We can use this method
to call a function defined within any model while passing parameters. The syntax
is slightly different than the previous one, and it is provided below.
<function id="function_id" model="model_name" name="method_name">
<value>param1</value>
<value>param2</value>
<!-- pass the parameters as per your need-->
</function>
The method's parameters are passed inside the value tag. It is possible to pass
as many parameters as you require. These parameters are accessible via the model's
method. An example is provided below
<odoo>
<data noupdate="1">
<function id="func_call_with_params" model="product.product" name="func_with_params">
<value>Cybrosys Technologies</value>
</function>
</data>
</odoo>
Also, we can pass parameters like the below code:
<value eval="[('name', '=', 'name_here'), ('module', '=', 'product')]" />
In summary, the eval attribute in the <value> tag is used to evaluate domain
expressions and other Python expressions dynamically. It allows to set the values
in XML without the need for hardcoding
The method definition should then be as follows.
from odoo import api, fields, models
class product(models.Model):
_inherit = "product.product"
@api.model
def func_with_params(self, name):
self.create(dict(name=name))
Then include the XML file within the manifest. The Python function will be called
when the custom module is installed. The parameter's value will be retrieved and
used to create the new product record.