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

Keyboard Shortcuts

Action NameDefault ShortcutMac OS X Shortcut
Open Odoo File Creation MenuAlt + Shift + F⌘ + ⇧ + F
Create Odoo Model FileAlt + Shift + D⌘ + ⇧ + D
Create Odoo View FileAlt + Shift + V⌘ + ⇧ + V
Create Odoo Access FileAlt + Shift + A⌘ + ⇧ + A

You can customize or add your own keyboard shortcuts by following these steps:

  1. Open Settings (or Preferences on macOS).
  2. Navigate to Keymap in the left sidebar.
  3. Expand the Plugins section.
  4. Locate and expand Cybrosys Assista: Odoo Helper from the list.
  5. Find the specific action you want to configure.
  6. Right-click on the action and choose Add Keyboard Shortcut.
  7. Press your desired key combination and apply the changes.

Tip: You can also remove or reassign conflicting shortcuts from the same menu.



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)

Context-Aware File Creation

The File Creator includes intelligent context-aware features that ensure files are created in appropriate locations and follow Odoo module structure conventions. Additionally, it automatically manages file registration in your module's configuration files.

Automatic File Registration

When you create new files using the File Creator, the plugin automatically:

Python Files

  • Models: Automatically adds model imports to __init__.py files
  • Controllers: Automatically adds controller imports to __init__.py files

XML Files

  • Views: Automatically adds view files to the data key in __manifest__.py

Benefits of Automatic Registration

  1. No Manual Updates: Eliminates the need to manually update __init__.py and __manifest__.py
  2. Reduces Errors: Prevents missing imports and data file references
  3. Maintains Consistency: Ensures all files are properly registered
  4. Saves Time: Focus on development instead of configuration management
  5. Team Efficiency: Standardized file registration across development teams

Directory Validation

  • Module Templates: Can only be created inside valid directories that follow Odoo module structure
  • File Placement: Automatically detects and validates target directory context
  • Structure Compliance: Ensures proper module organization from the start

Component-Specific Restrictions

Python File Creation

  • Models Directory: Python model files can only be created in models/ directories
  • Controllers Directory: Controller files restricted to controllers/ directories


XML File Creation

  • Views Directory: View files (form, list, search, kanban) restricted to views/ directories


Benefits of Context-Aware Creation

  1. Prevents Errors: Eliminates creation of files in wrong locations
  2. Maintains Structure: Ensures consistent module organization
  3. Follows Standards: Enforces Odoo development conventions
  4. Reduces Confusion: Clear guidance on where files should be placed
  5. Team Consistency: Standardized file organization across development teams

Smart Validation Features

  • Location Detection: Automatically identifies current directory context
  • Template Filtering: Shows only relevant templates based on location
  • Error Prevention: Prevents creation of incompatible file types in wrong directories
  • Guidance: Provides clear feedback when attempting to create files in invalid locations

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
  4. Context Awareness

    • Create files in the correct directories
    • Follow the component-specific restrictions
    • Leverage the smart validation features

Next Steps