File Creator
The File Creator lets you instantly generate specific Odoo files—Python, XML, and CSV—with pre-filled, context-aware templates tailored for Odoo modules. This feature helps you maintain consistency and follow best practices while reducing boilerplate code.
How to Use
- Right-click on the folder where you want the new file
- Select New → New Odoo File
- Choose the file type: Python, XML, or CSV
- Select the desired content template
- Name the file and press Enter
Supported File Types
Python Files
__init__.py
python
# -*- coding: utf-8 -*-
from . import models
from . import controllers
Basic initialization file with:
- Encoding declaration
- Import placeholders
__manifest__.py
python
# -*- coding: utf-8 -*-
{
'name': 'Module Name',
'version': '1.0',
'category': 'Uncategorized',
'summary': 'Module Summary',
'description': '''Module Description''',
'author': 'Your Company',
'website': 'https://www.yourcompany.com',
'depends': ['base'],
'data': [
'security/ir.model.access.csv',
'views/views.xml',
],
'installable': True,
'application': False,
'auto_install': False,
}
Ready-to-edit manifest file with:
- Standard metadata
- Name, version, category
- Dependencies
- Data files
Odoo Model
python
# -*- coding: utf-8 -*-
from odoo import api, fields, models
class ModelName(models.Model):
""" This model represents model.name."""
_name = 'model.name'
_description = 'ModelName'
name = fields.Char(string='Customer Name', required=True)
active = fields.Boolean(default=True)
@api.model_create_multi
def create(self, vals):
"""Override the default create method to customize record creation logic."""
return super().create(vals)
Model definition file with:
- Required imports
- Sample model class
- Fields
- Basic
create
method
Odoo Controller
python
# -*- coding: utf-8 -*-
from odoo import http
from odoo.http import request
class MainController(http.Controller):
"""Controller class to handle HTTP routes."""
@http.route('/main', auth='public', website=True)
def index(self, **kw):
return request.render('your_module.template_id', {'sample_data': 'Sample Data'})
Controller file including:
- Required imports
- Controller class
- Sample
@http.route
methods - Web/API endpoints
XML Files
Empty XML
xml
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- Your custom views here -->
</odoo>
Blank XML file for:
- Custom configurations
- Advanced use cases
Basic View XML
xml
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- Form View -->
<record id="model_name_view_form" model="ir.ui.view">
<field name="name">model.name.view.form</field>
<field name="model">model.name</field>
<field name="arch" type="xml">
<form string="Model_name">
<sheet>
<group>
<field name="name"/>
<!-- Add your fields here -->
</group>
</sheet>
</form>
</field>
</record>
<!-- List View -->
<record id="model_name_view_list" model="ir.ui.view">
<field name="name">model.name.view.list</field>
<field name="model">model.name</field>
<field name="arch" type="xml">
<list string="Model_name">
<field name="name"/>
<!-- Add your fields here -->
</list>
</field>
</record>
<!-- Action -->
<record id="model_name_action" model="ir.actions.act_window">
<field name="name">Model name</field>
<field name="res_model">model.name</field>
<field name="view_mode">list,form</field>
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">
Create your first model name!
</p>
</field>
</record>
<!-- Menu -->
<menuitem id="model_name_menu"
name="Model name"
action="model_name_action"
sequence="10"/>
</odoo>
Minimal view definitions:
- Form views
- Tree views
- Basic fields
- Standard attributes
Advanced View XML
xml
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- Form View -->
<record id="model_name_view_form" model="ir.ui.view">
<field name="name">model.name.view.form</field>
<field name="model">model.name</field>
<field name="arch" type="xml">
<form string="Model_name">
<header>
<button name="action_confirm" string="Confirm" type="object" class="oe_highlight"/>
<button name="action_cancel" string="Cancel" type="object"/>
<field name="state" widget="statusbar" statusbar_visible="draft,confirmed,done"/>
</header>
<sheet>
<div class="oe_title">
<h1>
<field name="name"/>
</h1>
</div>
<notebook>
<page string="General Information">
<group>
<group>
<field name="field1"/>
<field name="field2"/>
</group>
<group>
<field name="field3"/>
<field name="field4"/>
</group>
</group>
</page>
<page string="Lines">
<field name="line_ids">
<list editable="bottom">
<field name="name"/>
<field name="description"/>
<field name="quantity"/>
<field name="price"/>
<field name="subtotal" sum="Total"/>
</list>
</field>
</page>
<page string="Notes">
<field name="notes"/>
</page>
</notebook>
</sheet>
<chatter/>
</form>
</field>
</record>
<!-- List View -->
<record id="model_name_view_list" model="ir.ui.view">
<field name="name">model.name.view.list</field>
<field name="model">model.name</field>
<field name="arch" type="xml">
<list string="Model_name" decoration-info="state=='draft'" decoration-success="state=='done'" decoration-warning="state=='confirmed'">
<field name="name"/>
<field name="field1"/>
<field name="field2"/>
<field name="create_date"/>
<field name="state"/>
</list>
</field>
</record>
<!-- Search View -->
<record id="model_name_view_search" model="ir.ui.view">
<field name="name">model.name.view.search</field>
<field name="model">model.name</field>
<field name="arch" type="xml">
<search string="Search Model_name">
<field name="name"/>
<field name="field1"/>
<field name="field2"/>
<separator/>
<filter string="Draft" name="draft" domain="[('state','=','draft')]"/>
<filter string="Confirmed" name="confirmed" domain="[('state','=','confirmed')]"/>
<filter string="Done" name="done" domain="[('state','=','done')]"/>
<group expand="0" string="Group By">
<filter string="State" name="groupby_state" context="{'group_by': 'state'}"/>
<filter string="Creation Date" name="groupby_create_date" context="{'group_by': 'create_date:month'}"/>
</group>
</search>
</field>
</record>
<!-- Calendar View -->
<record id="model_name_view_calendar" model="ir.ui.view">
<field name="name">model.name.view.calendar</field>
<field name="model">model.name</field>
<field name="arch" type="xml">
<calendar string="Model_name" date_start="create_date" color="state">
<field name="name"/>
<field name="state"/>
</calendar>
</field>
</record>
<!-- Kanban View -->
<record id="model_name_view_kanban" model="ir.ui.view">
<field name="name">model.name.view.kanban</field>
<field name="model">model.name</field>
<field name="arch" type="xml">
<kanban default_group_by="state" class="o_kanban_small_column" sample="1">
<field name="name"/>
<field name="state"/>
<field name="field1"/>
<field name="field2"/>
<templates>
<t t-name="kanban-box">
<div class="oe_kanban_global_click">
<div class="oe_kanban_details">
<strong class="o_kanban_record_title">
<field name="name"/>
</strong>
<div class="o_kanban_tags_section">
<ul>
<li><field name="field1"/></li>
<li><field name="field2"/></li>
</ul>
</div>
</div>
</div>
</t>
</templates>
</kanban>
</field>
</record>
<!-- Actions -->
<record id="model_name_action" model="ir.actions.act_window">
<field name="name">Model name</field>
<field name="res_model">model.name</field>
<field name="view_mode">list,form,kanban,calendar</field>
<field name="search_view_id" ref="model_name_view_search"/>
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">
Create your first model name!
</p>
</field>
</record>
<!-- Menu -->
<menuitem id="model_name_menu"
name="Model name"
action="model_name_action"
sequence="10"/>
</odoo>
Complex views featuring:
- Groups
- Notebooks
- Status bars
- Rich UI layouts
Inherited View XML
xml
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- Inherit Form View -->
<record id="model_name_view_form" model="ir.ui.view">
<field name="name">model.name.view.form.inherit.module</field>
<field name="model">model.name</field>
<field name="inherit_id" ref="module.original_form_view_id"/>
<field name="arch" type="xml">
<!-- Add fields to an existing group -->
<xpath expr="//group[1]" position="inside">
<field name="new_field1"/>
<field name="new_field2"/>
</xpath>
<!-- Add a new page to the notebook -->
<xpath expr="//notebook" position="inside">
<page string="New Page">
<group>
<field name="new_field3"/>
<field name="new_field4"/>
</group>
</page>
</xpath>
<!-- Modify an existing field -->
<xpath expr="//field[@name='existing_field']" position="attributes">
<attribute name="readonly">1</attribute>
<attribute name="string">New Label</attribute>
</xpath>
<!-- Replace a field -->
<xpath expr="//field[@name='to_replace']" position="replace">
<field name="replacement_field"/>
</xpath>
<!-- Add before a specific field -->
<xpath expr="//field[@name='reference_field']" position="before">
<field name="before_field"/>
</xpath>
<!-- Add after a specific field -->
<xpath expr="//field[@name='reference_field']" position="after">
<field name="after_field"/>
</xpath>
</field>
</record>
<!-- Inherit List View -->
<record id="model_name_view_list" model="ir.ui.view">
<field name="name">model.name.view.list.inherit.module</field>
<field name="model">model.name</field>
<field name="inherit_id" ref="module.original_list_view_id"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='reference_field']" position="after">
<field name="new_field"/>
</xpath>
</field>
</record>
</odoo>
Template for extending views:
<xpath>
usage- View inheritance
- Field modifications
Report XML
xml
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- Report Action -->
<record id="module_action_report" model="ir.actions.report">
<field name="name">Module Report</field>
<field name="model">module</field>
<field name="report_type">qweb-pdf</field>
<field name="report_name">module.report_module</field>
<field name="report_file">module.report_module</field>
<field name="binding_model_id" ref="model_module"/>
<field name="binding_type">report</field>
</record>
<!-- Report Template -->
<template id="report_module_document">
<t t-call="web.external_layout">
<t t-set="doc" t-value="doc.with_context(lang=doc.partner_id.lang)" />
<div class="page">
<div class="oe_structure"/>
<h2>
<span t-field="doc.name"/>
</h2>
<div class="row mt32 mb32">
<div class="col-auto">
<strong>Field 1:</strong>
<p t-field="doc.field1"/>
</div>
<div class="col-auto">
<strong>Field 2:</strong>
<p t-field="doc.field2"/>
</div>
<div class="col-auto">
<strong>Date:</strong>
<p t-field="doc.create_date"/>
</div>
</div>
<table class="table table-sm o_main_table">
<thead>
<tr>
<th name="th_description" class="text-left">Description</th>
<th name="th_quantity" class="text-right">Quantity</th>
<th name="th_price" class="text-right">Price</th>
<th name="th_subtotal" class="text-right">Subtotal</th>
</tr>
</thead>
<tbody>
<t t-foreach="doc.line_ids" t-as="line">
<tr>
<td name="td_description"><span t-field="line.description"/></td>
<td name="td_quantity" class="text-right"><span t-field="line.quantity"/></td>
<td name="td_price" class="text-right"><span t-field="line.price"/></td>
<td name="td_subtotal" class="text-right"><span t-field="line.subtotal"/></td>
</tr>
</t>
</tbody>
</table>
<div class="row">
<div class="col-4 offset-8">
<table class="table table-sm">
<tr class="border-black">
<td><strong>Total</strong></td>
<td class="text-right">
<span t-field="doc.total"/>
</td>
</tr>
</table>
</div>
</div>
<div class="oe_structure"/>
</div>
</t>
</template>
<template id="report_module">
<t t-call="web.html_container">
<t t-foreach="docs" t-as="doc">
<t t-call="module.report_module_document" t-lang="doc.partner_id.lang"/>
</t>
</t>
</template>
</odoo>
Printable report templates:
- PDF/HTML output
- Report actions
- QWeb templates
Security Group XML
xml
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- Custom Groups -->
<record id="module_name_group_user" model="res.groups">
<field name="name">Module name groups User</field>
<field name="category_id" ref="base.module_category_hidden"/>
<field name="comment">Basic access to Module name groups</field>
<field name="implied_ids" eval="[(4, ref('base.group_user'))]"/>
</record>
<record id="module_name_group_manager" model="res.groups">
<field name="name">Module name groups Manager</field>
<field name="category_id" ref="base.module_category_hidden"/>
<field name="comment">Full access to Module name groups</field>
<field name="implied_ids" eval="[(4, ref('module_name_group_user'))]"/>
</record>
<!-- Sample Users Data -->
<record id="module_name_group_demo_user" model="res.users">
<field name="name">Module name groups Demo User</field>
<field name="login">module_name_groups_demo_user</field>
<field name="password">module_name_groups_demo_user</field>
<field name="email">module_name_groups_demo_user@example.com</field>
<field name="groups_id" eval="[(4, ref('module_name_group_user'))]"/>
</record>
</odoo>
Two access groups:
User
: Basic access groupManager
: Inherits permissions fromUser
- Hierarchical permissions using
implied_ids
- Demo user assigned to the
User
group
Security Rule XML
xml
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- Access Rights -->
<record id="access_model_name_user" model="ir.model.access">
<field name="name">model.name.user</field>
<field name="model_id" ref="model_model_name"/>
<field name="group_id" ref="model_name_group_user"/>
<field name="perm_read" eval="1"/>
<field name="perm_write" eval="1"/>
<field name="perm_create" eval="1"/>
<field name="perm_unlink" eval="0"/>
</record>
<record id="access_model_name_manager" model="ir.model.access">
<field name="name">model.name.manager</field>
<field name="model_id" ref="model_model_name"/>
<field name="group_id" ref="model_name_group_manager"/>
<field name="perm_read" eval="1"/>
<field name="perm_write" eval="1"/>
<field name="perm_create" eval="1"/>
<field name="perm_unlink" eval="1"/>
</record>
<!-- Record Rules -->
<record id="model_name_rule_user" model="ir.rule">
<field name="name">model.name: Users access only their own records</field>
<field name="model_id" ref="model_model_name"/>
<field name="domain_force">[('create_uid', '=', user.id)]</field>
<field name="perm_read" eval="1"/>
<field name="perm_write" eval="1"/>
<field name="perm_create" eval="1"/>
<field name="perm_unlink" eval="0"/>
<field name="groups" eval="[(4, ref('model_name_group_user'))]"/>
</record>
<record id="model_name_rule_manager" model="ir.rule">
<field name="name">model.name: Managers access all records</field>
<field name="model_id" ref="model_model_name"/>
<field name="domain_force">[(1, '=', 1)]</field>
<field name="perm_read" eval="1"/>
<field name="perm_write" eval="1"/>
<field name="perm_create" eval="1"/>
<field name="perm_unlink" eval="1"/>
<field name="groups" eval="[(4, ref('model_name_group_manager'))]"/>
</record>
</odoo>
Two access groups:
User
: Can read, write, and create only their own records (unlink
disabled)Manager
: Full access to all records includingunlink
- Model-level access set via
ir.model.access
- Record-level domain-based filtering using
ir.rule
- Controlled visibility and permission enforcement for groups:
model_name_group_user
andmodel_name_group_manager
Sequence XML
xml
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data noupdate="1">
<!-- Sequence -->
<record id="seq_ir_sequence_data" model="ir.sequence">
<field name="name">Ir sequence data Sequence</field>
<field name="code">ir.sequence.data</field>
<field name="prefix">IR_/%(year)s/</field>
<field name="padding">5</field>
<field name="company_id" eval="False"/>
</record>
</data>
</odoo>
sequence data
records:
- code
- prefix
- padding
- company_id
Settings XML
xml
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- Inherit Res Config Settings Form -->
<record id="res_config_settings_view_form" model="ir.ui.view">
<field name="name">res.config.settings.view.form.inherit.res_config_settings</field>
<field name="model">res.config.settings</field>
<field name="inherit_id" ref="base.res_config_settings_view_form"/>
<field name="arch" type="xml">
<xpath expr="//div[@id='settings']" position="inside">
<div class="app_settings_block" data-string="Res config settings Settings">
<h2>Res config settings Settings</h2>
<group>
<field name="your_field_setting"/>
<!-- Add more fields if needed -->
</group>
</div>
</xpath>
</field>
</record>
</odoo>
Custom settings templates:
- Config panels
- System parameters
- User preferences
Cron Job XML
xml
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data noupdate="1">
<!-- Scheduled Action -->
<record id="ir_cron_ir_cron_data" model="ir.cron">
<field name="name">Ir cron data Scheduler</field>
<field name="model_id" ref="model_ir_cron_data"/>
<field name="state">code</field>
<field name="code">
model.method_to_run()
</field>
<field name="interval_number">1</field>
<field name="interval_type">days</field>
<field name="numbercall">-1</field>
<field name="active" eval="True"/>
</record>
</data>
</odoo>
Scheduled actions:
- Recurring jobs
- Methods
- Intervals
- Active states
CSV Files
Security File
csv
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_model_name_user,access.model.name.user,model_model_name,base.group_user,1,1,1,1
Access control rules:
- Model names
- Groups
- Permissions (read, write, create, delete)
Best Practices
Naming Conventions
- Use lowercase with underscores for Python files
- Use descriptive names for XML files
- Follow Odoo's naming conventions
File Organization
- Keep related files together
- Use appropriate subdirectories
- Maintain module structure
Template Selection
- Choose the most appropriate template
- Customize as needed
- Remove unused code
Next Steps
- Learn about Module Templates for creating complete modules
- Explore Code Snippets for quick code generation
- Check out Best Practices for file organization