Skip to content

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

  1. Right-click on the folder where you want the new file
  2. Select New → New Odoo File
  3. Choose the file type: Python, XML, or CSV
  4. Select the desired content template
  5. 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 group
  • Manager: Inherits permissions from User
  • 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 including unlink
  • 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 and model_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

  1. Naming Conventions

    • Use lowercase with underscores for Python files
    • Use descriptive names for XML files
    • Follow Odoo's naming conventions
  2. File Organization

    • Keep related files together
    • Use appropriate subdirectories
    • Maintain module structure
  3. Template Selection

    • Choose the most appropriate template
    • Customize as needed
    • Remove unused code

Next Steps