Getting Started with Odoo Development

13 min read

In this article by Daniel Reis, author of the book Odoo Development Essentials, we will see how to get started with Odoo.

Odoo is a powerful open source platform for business applications. A suite of closely integrated applications was built on it, covering all business areas from CRM and Sales to Accounting and Stocks. Odoo has a dynamic and growing community around it, constantly adding features, connectors, and additional business apps. Many can be found at

In this article, we will guide you to install Odoo from the source code and create your first Odoo application. Inspired by the project, we will build a simple to-do application. It should allow us to add new tasks, mark them as completed, and finally, clear the task list from all already completed tasks.

(For more resources related to this topic, see here.)

Installing Odoo from source

We will use a Debian/Ubuntu system for our Odoo server, so you will need to have it installed and available to work on. If you don’t have one, you might want to set up a virtual machine with a recent version of Ubuntu Server before proceeding.

For a development environment, we will install it directly from Odoo’s Git repository. This will end up giving more control on versions and updates. We will need to make sure Git is installed. In the terminal, type the following command:

$ sudo apt-get update && sudo apt-get upgrade # Update system
$ sudo apt-get install git # Install Git

To keep things tidy, we will keep all our work in the /odoo-dev directory inside our home directory:

$ mkdir ~/odoo-dev # Create a directory to work in
$ cd ~/odoo-dev # Go into our work directory

Now, we can use this script to show how to install Odoo from source code in a Debian system:

$ git clone -b 8.0 --depth=1
$ ./odoo/ setup_deps # Installs Odoo system dependencies
$ ./odoo/ setup_pg   # Installs PostgreSQL & db superuser

Quick start an Odoo instance

In Odoo 8.0, we can create a directory and quick start a server instance for it. We can start by creating the directory called todo-app for our instance as shown here:

$ mkdir ~/odoo-dev/todo-app
$ cd ~/odoo-dev/todo-app

Now we can create our todo_minimal module in it and initialize the Odoo instance:

$ ~/odoo-dev/odoo/ scaffold todo_minimal
$ ~/odoo-dev/odoo/ start -i todo_minimal

The scaffold command creates a module directory using a predefined template.

The start command creates a database with the current directory name and automatically adds it to the addons path so that its modules are available to be installed. Additionally, we used the -i option to also install our todo_minimal module.

It will take a moment to initialize the database, and eventually we will see an INFO log message Modules loaded. Then, the server will be ready to listen to client requests.

By default, the database is initialized with demonstration data, which is useful for development databases. Open http://<server-name>:8069 in your browser to be presented with the login screen. The default administrator account is admin with the password admin. Whenever you want to stop the Odoo server instance and return to the command line, press CTRL + C.

If you are hosting Odoo in a virtual machine, you might need to do some network configuration to be able to use it as a server. The simplest solution is to change the VM network type from NAT to Bridged. Hopefully, this can help you find the appropriate solution in your virtualization software documentation.

Creating the application models

Now that we have an Odoo instance and a new module to work with, let’s start by creating the data model. Models describe business objects, such as an opportunity, a sales order, or a partner (customer, supplier, and so on). A model has data fields and can also define specific business logic.

Odoo models are implemented using a Python class derived from a template class. They translate directly to database objects, and Odoo automatically takes care of that when installing or upgrading the module.

Let’s edit the file in the todo_minimal module directory so that it contains this:

# -*- coding: utf-8 -*-
from openerp import models, fields, api
class TodoTask(models.Model):
   _name = 'todo.task'
   name = fields.Char()
   is_done = fields.Boolean()
   active = fields.Boolean(default=True)

Our to-do tasks will have a name title text, a done flag, and an active flag. The active field has a special meaning for Odoo; by default, records with a False value in it won’t be visible to the user. We will use it to clear the tasks out of sight without actually deleting them.

Upgrading a module

For our changes to take effect, the module has to be upgraded.

The simplest and fastest way to make all our changes to a module effective is to go to the terminal window where you have Odoo running, stop it (CTRL + C), and then restart it requesting the module upgrade.

To start upgrading the server, the todo_minimal module in the todo-app database, use the following command:

$ cd ~/odoo-dev/todo-app # we should be in the right directory
$ ./ start -u todo_minimal

The -u option performs an upgrade on a given list of modules. In this case, we upgrade just the todo_minimal module.

Developing a module is an iterative process. You should make your changes in gradual steps and frequently install them with a module upgrade. Doing so will make it easier to detect mistakes sooner, and narrowing down the culprit in case the error message is not clear enough. And this can be very frequent when starting with Odoo development.

Adding menu options

Now that we have a model to store our data, let’s make it available on the user interface. All we need is to add a menu option to open the to-do task model, so it can be used. This is done using an XML data file.

Let’s reuse the templates.xml data file and edit it so that it look like this:

   <act_window id="todo_task_action"
               name="To-do Task Action"
                   res_model="todo.task" view_mode="tree,form" />
       <menuitem id="todo_task_menu"
                name="To-do Tasks"
                 sequence="20" />

Here, we have two records: a menu option and a window action. The Communication top menu to the user interface was added by the mail module dependency. We can know the identifier of the specific menu option where we want to add our own menu option by inspecting that module, it is mail_feeds. Also, our menu option executes the todo_task_action action we created. And that window action opens a tree view for the todo.task model.

If we upgrade the module now and try the menu option just added, it will open an automatically generated view for our model, allowing to add and edit records.

Views should be defined for models to be exposed to the users, but Odoo is nice enough to do that automatically if we don’t, so we can work with our model right away, without having any form or list views defined yet.

So far so good. Let’s improve our user interface now.

Creating Views

Odoo supports several types of views, but the more important ones are list (also known as “tree”), form, and search views. For our simple module, we will just add a list view. Edit the templates.xml file to add the following <record> element just after the <data> opening tag at the top:

   <record id="todo_task_tree" model="ir.ui.view">
       <field name="name">To-do Task Form</field>
       <field name="model">todo.task</field>
       <field name="arch" type="xml">
           <tree editable="top" colors="gray:is_done==True">
               <field name="name" />
               <field name="is_done" />

This creates a tree view for the todo.task model with two columns: the title name and the is_done flag. Additionally, it has a color rule to display the tasks done in gray.

Adding business logic

We want to add business logic to be able to clear the already completed tasks. Our plan is to add an option on the More button, shown at the top of the list when we select lines. We will use a very simple wizard for this, opening a confirmation dialog, where we can execute a method to inactivate the done tasks.

Wizards use a special type of model for temporary data: a Transient model. We will now add it to the file as follows:

class TodoTaskClear(models.TransientModel):

   _name = 'todo.task.clear'
   def do_clear_done(self):
       Task = self.env['todo.task']
       done_recs =[('is_done', '=', True)])
       done_recs.write({'active': False)}
       return True

Transient models work just like regular models, but their data is temporary and will eventually be purged from the database. In this case, we don’t need any fields, since no additional input is going to be asked to the user. It just has a method that will be called when the confirmation button is pressed. It lists all tasks that are done and then sets their active flag to False.

Next, we need to add the corresponding user interface. In the templates.xml file, add the following code:

   <record id="todo_task_clear_dialog" model="ir.ui.view">
     <field name="name">To-do Clear Wizard</field>
     <field name="model">todo.task.clear</field>
     <field name="arch" type="xml">
          All done tasks will be cleared, even if
               <button type="object"
                       " class="oe_highlight" />
               or <button special="cancel"
   <!-- More button Action -->
   <act_window id="todo_task_clear_action"
       name="Clear Done"
       target="new" multi="True" />

The first record defines the form for the dialog window. It has a confirmation text and two buttons on the footer: Clear and Cancel. The Clear button when pressed will call the do_clear_done() method defined earlier. The second record is an action that adds the corresponding option in the More button for the to-do tasks model.

Configuring security

Finally, we need to set the default security configurations for our module. These configurations are usually stored inside the security/ directory. We need to add them to the manifest file. Change the data attribute to the following:

'data': [

The access control lists are defined for models and user groups in the ir.model.access.csv file. There is a pre-generated template. Edit it to look like this:

access_todo_task_user,To-do Task User Access,model_todo_task,base.group_user,1,1,1,1

This gives full access to all users in the base group named Employees.

However, we want each user to see only their own to-do tasks. For that, we need a record rule setting a filter on the records the base group can see. Inside the security/ directory, add a todo_access_rules.xml file to define the record rule:

   <record id="todo_task_user_rule" model="ir.rule">
       <field name="name">ToDo Tasks only for owner</field>
       <field name="model_id" ref="model_todo_task"/>
       <field name="domain_force">[('create_uid','=',]    
       <field name="groups"
               eval="[(4, ref('base.group_user'))]"/>
This is all we need to set up the module security.


We created a new module from start, covering the most frequently used elements in a module: models, user interface views, business logic in model methods, and access security. In the process, we got familiar with the module development process, involving module upgrades and application server restarts to make the gradual changes effective in Odoo.

Resources for Article:

Further resources on this subject:


Please enter your comment!
Please enter your name here