What Are Data Files?
Data files load records into Odoo during module installation or upgrade. They define: configuration settings, default categories, email templates, security rules, demo data, and any records your module needs to function. Listed in __manifest__.py under data or demo.
XML Data Files
Basic Record Creation
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data>
<record id="department_engineering" model="hr.department">
<field name="name">Engineering</field>
</record>
<record id="department_sales" model="hr.department">
<field name="name">Sales</field>
</record>
</data>
</odoo>Field Types
<!-- Char/Text -->
<field name="name">My Record</field>
<!-- Integer/Float -->
<field name="sequence">10</field>
<field name="price">99.99</field>
<!-- Boolean -->
<field name="active" eval="True"/>
<!-- Date -->
<field name="date_start">2026-01-01</field>
<!-- Selection -->
<field name="state">draft</field>
<!-- Many2one (reference) -->
<field name="company_id" ref="base.main_company"/>
<field name="department_id" ref="department_engineering"/>
<!-- Many2many -->
<field name="tag_ids" eval="[(6, 0, [ref('tag_important'), ref('tag_urgent')])]" />
<!-- One2many -->
<field name="line_ids">
<record id="line_1" model="my.model.line">
<field name="name">Line 1</field>
<field name="quantity">5</field>
</record>
</field>
<!-- HTML -->
<field name="description" type="html">
<p>Rich <b>HTML</b> content</p>
</field>
<!-- Binary (base64 file) -->
<field name="image" type="base64" file="my_module/static/img/logo.png"/>eval Expressions
<!-- Python expressions -->
<field name="active" eval="True"/>
<field name="sequence" eval="10"/>
<!-- Reference to another record's ID -->
<field name="parent_id" eval="ref('my_module.parent_record')"/>
<!-- Many2many command tuples -->
<field name="group_ids" eval="[(4, ref('base.group_user'))]" />
<!-- Date computation -->
<field name="date" eval="(datetime.now() + relativedelta(days=30)).strftime('%Y-%m-%d')"/>
<!-- Conditional value -->
<field name="company_id" eval="ref('base.main_company') if ref('base.main_company') else False"/>noupdate Flag
<!-- noupdate="1": records are created on install but NOT updated on upgrade -->
<data noupdate="1">
<record id="email_template_welcome" model="mail.template">
<field name="name">Welcome Email</field>
<field name="subject">Welcome!</field>
<field name="body_html"><p>Welcome to our platform.</p></field>
</record>
</data>
<!-- noupdate="0" (default): records are updated on every upgrade -->
<data noupdate="0">
<record id="menu_main" model="ir.ui.menu">
<field name="name">Main Menu</field>
</record>
</data>When to Use noupdate
Use noupdate="1" | Use noupdate="0" |
|---|---|
| Email templates (user may customize) | Views (always managed by module) |
| Default categories/tags | Menu items |
| Cron jobs (user may change schedule) | Security rules |
| Demo data | Actions |
| Initial configuration values | Report definitions |
CSV Data Files
CSV is ideal for bulk data like access rules and simple records.
# security/ir.model.access.csv
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_my_model_user,my.model.user,model_my_model,base.group_user,1,1,1,0
access_my_model_admin,my.model.admin,model_my_model,base.group_system,1,1,1,1# data/categories.csv
id,name,sequence
my_module.cat_electronics,Electronics,10
my_module.cat_clothing,Clothing,20
my_module.cat_food,Food & Beverage,30__manifest__.py Ordering
'data': [
# 1. Security first (access rules needed by other records)
'security/ir.model.access.csv',
'security/record_rules.xml',
# 2. Data/seed records (categories, templates, etc.)
'data/categories.xml',
'data/email_templates.xml',
'data/cron_jobs.xml',
# 3. Views and actions
'views/my_model_views.xml',
'views/menu.xml',
# 4. Reports
'report/my_report.xml',
],
'demo': [
# Demo data only loaded when demo mode is enabled
'demo/demo_data.xml',
],Special XML Elements
<!-- Delete a record -->
<delete model="ir.ui.menu" id="sale.menu_old_feature"/>
<!-- Function call -->
<function model="res.company" name="_init_settings"/>
<!-- Menuitem shortcut -->
<menuitem id="menu_root" name="My App" sequence="100"/>
<menuitem id="menu_list" name="Records" parent="menu_root"
action="action_my_model"/>
<!-- Template (QWeb) -->
<template id="my_template">
<div class="container">...</div>
</template>Common Mistakes
- Wrong file order in manifest — Security must come before data that references groups
- Missing XML ID prefix — Always include module name when referencing:
ref('my_module.record_id') - Using noupdate for views — Views should always update on upgrade (
noupdate="0") - Forgetting CSV header — CSV must have the exact header format:
id,name,model_id:id,... - XML encoding — Always use
encoding="utf-8"in the XML declaration