---
url: https://docs.cybrosys.com/vs-code-extension/features/file-creator.md
description: >-
  Create Odoo models, controllers, views, reports and security files from the
  Explorer, with templates that follow your Odoo version.
---

# File creator

Create Odoo Python, XML and security files from the Explorer, with templates for views, reports, groups, rules, sequences, settings and cron jobs. The templates follow your Odoo version.

## What you can do

Right-click a folder in the Explorer and open **Assista Odoo**.

| Menu path | What it creates |
|---|---|
| **Create Odoo File** > **Create Model File** | `__init__.py`, `__manifest__.py`, an Odoo model or an Odoo controller. |
| **Create Odoo File** > **Create View File** | An XML file from one of ten templates. |
| **Create Odoo File** > **Create Security File** | A row in the access file of your Odoo version. |
| **Create Odoo File** > **Add to `__init__.py`** | An import line in the parent `__init__.py`. |
| **Create Odoo Report** > **Create PDF Report** or **Create HTML Report** | A report XML file (the Report View template) with the report type set. |

**Add to `__init__.py`** is also in the editor and Explorer context menus for Python files and folders. **Add File to Manifest** is a Command Palette command (see [Tips and limits](#tips-and-limits)).

## Get started

1. Right-click a folder inside your module, such as `models`, `views` or `security`.
2. Select **Assista Odoo** > **Create Odoo File**, then pick the entry.
3. Choose a template, enter a file name and press **Enter**.

### File name rules

* Use lowercase letters and `_` only. Digits, dots and spaces are rejected. Do not type the extension.
* Model, controller and view files cannot be created at the module root or outside a module. Right-click a subfolder such as `models` or `views`.
* If a file with the same name exists, the extension warns you and does not overwrite it.
* Views open after creation. Python files are created without opening.

### How the model is chosen

XML templates are written for a model taken from the file name. The extension strips a trailing `_views`, `_view`, `_templates`, `_data`, `_report`, `_reports`, `_security` or `_menus`, then looks for an indexed model whose name matches. If none matches, underscores become dots.

| You enter | Model | IDs start with |
|---|---|---|
| `sale_order_views` | `sale.order` | `sale_order` |
| `library_book_views` | `library.book` | `library_book` |

Create the model first so the index can match it. Templates also contain placeholder fields (`field1` to `field4`, `line_ids`, `notes`, `total`, `your_field_setting`). Replace them with your model's fields.

## Python templates

Choose these under **Create Model File**.

| Template | What it creates |
|---|---|
| **`__init__`** | `__init__.py` with the encoding line and `from . import `, ready for you to finish. Needs no name. |
| **`__manifest__`** | `__manifest__.py` with `name`, `version`, `category`, `summary`, `description`, `author`, `website`, `depends` (`base`), `data` (the access file of your version and `views/views.xml`), `license` (`LGPL-3`), `installable`, `application` and `auto_install`. Needs no name. |
| **Odoo Model** | `<name>.py` with a class named after the file, `_name` with dots (`sale_order` gives `sale.order`) and a `name` field. |
| **Odoo Controller** | `<name>.py` with a `MainController` class and a public `@http.route('/my_module/my_module')` that returns `"Hello, world"`. |

After you create a model or controller, run **Add to `__init__.py`** so Odoo imports it.

## XML templates

Choose these under **Create View File**. IDs use your file name, for example `sale_order_view_form`.

| Template | What it generates |
|---|---|
| **Empty View** | An empty `<odoo>` file with a comment. |
| **Basic View** | A form view, a list view, a window action (`list,form`) with a help message, and a menu item. |
| **Advanced View** | A form with header buttons (**Confirm**, **Cancel**) and a status bar, a title block, two-column group, a notebook with an editable lines list and notes, and chatter. Also a list with row decorations, a search view with filters and group by, a calendar, a kanban, a window action for all four views, and a root menu with a sub-menu. |
| **Inherit View** | A form and a list inheriting `module.original_form_view_id` and `module.original_list_view_id`, with `xpath` examples for `inside`, `attributes`, `replace`, `before` and `after`. Replace the placeholder view IDs. |
| **Report View** | An `ir.actions.report` record bound to the model, and a QWeb document template based on `web.external_layout` with header fields and a lines table. The entry point iterates `docs`. |
| **Security Group View** | A **User** group and a **Manager** group, where Manager implies User. See [Version differences](#version-differences). |
| **Security Rule View** | Access rights for those two groups, and an own-records restriction for users. See [Version differences](#version-differences). |
| **Sequence View** | A `noupdate` `ir.sequence` with a year prefix and padding 5. A comment shows how to call it with `next_by_code`. |
| **Settings View** | A settings app, block and setting inside `base.res_config_settings_view_form`, plus a window action for `res.config.settings`. Replace `your_field_setting`. |
| **Cron Job View** | A `noupdate` `ir.cron` that runs `model._cron_<name>()` daily as the root user. Define that method on your model. |

**Create PDF Report** and **Create HTML Report** use the Report View template, with the report type set to `qweb-pdf` or `qweb-html`, and the module name in `report_name`.

### Version differences

The XML templates match the conventions of each Odoo version.

**Odoo 20**
Security rules and record rules are `ir.access` records. Each has an `operation` (a subset of `crud`) and an optional `domain`.

```xml
<record id="access_library_book_user" model="ir.access">
    <field name="name">library.book: user</field>
    <field name="model_id" ref="model_library_book"/>
    <field name="group_id" ref="group_library_book_user"/>
    <field name="operation">cru</field>
    <field name="domain">[('create_uid', '=', user.id)]</field>
</record>
```

Groups belong to a privilege (`res.groups.privilege`), and the Report View has no `report_file` field.

**Odoo 19**
Access rights are `ir.model.access` records, with an `ir.rule` for the own-records restriction. Groups belong to a privilege (`res.groups.privilege`) and list their users in `user_ids`. The Report View includes `report_file`.

```xml
<record id="access_library_book_user" model="ir.model.access">
    <field name="name">library.book.user.access</field>
    <field name="model_id" ref="model_library_book"/>
    <field name="group_id" ref="group_library_book_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>
```

**Odoo 18**
Access rights are `ir.model.access` records, with an `ir.rule` for the own-records restriction. Groups use `category_id`, and the Security Group View also adds a demo user. The Report View includes `report_file`.

## Create Security File

Use this to add an access row for a model without opening the CSV.

1. Right-click the module's `security` folder.
2. Select **Assista Odoo** > **Create Odoo File** > **Create Security File**.
3. Enter the model's technical name, for example `sale.order`.

The extension creates the access file of your version with its header if it does not exist, adds a full-access row for internal users (`base.group_user`) and opens it.

| Odoo version | File | Header |
|---|---|---|
| 18 and 19 | `security/ir.model.access.csv` | `id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink` |
| 20 | `security/ir.access.csv` | `id,name,model_id,group_id/id,operation,domain` |

**Odoo 20**

```csv
id,name,model_id,group_id/id,operation,domain
access_sale_order_user,sale.order user,sale.order,base.group_user,crud,
```

**Odoo 18 and 19**

```csv
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_sale_order_user,sale.order user,model_sale_order,base.group_user,1,1,1,1
```

This command only works on the `security` folder of a module. It appends a row each time you run it, and does not add the file to the manifest. To avoid duplicates and update the manifest automatically, use **Create Access Right** from a model class. See [Model tools](/vs-code-extension/features/model-tools).

## Register a file

**Add to `__init__.py`** adds `from . import <name>` for a Python file or a folder to the `__init__.py` next to it. It creates `__init__.py` if it is missing, and does nothing if the import is already there. It works only for Python files and folders.

**Add File to Manifest** adds the current file to the manifest `data` list. Run it from the Command Palette (`Ctrl+Shift+P`, or `Cmd+Shift+P` on macOS).

## Tips and limits

* **Add File to Manifest** adds to the `data` list only, and needs that list to exist.
* Generated XML files are not added to the manifest. Use **Add File to Manifest**, or list them yourself.
* Check the Odoo version in the status bar before you create files. Click it to change the version.
* To create views, a report or an access rule from an existing model class, use [Model tools](/vs-code-extension/features/model-tools).

## Next steps

* [Generate views and reports from a model](/vs-code-extension/features/model-tools)
* [Create a whole module](/vs-code-extension/features/module-templates)
* [Insert snippets](/vs-code-extension/snippets)
