Odoo provides a rapid application development framework that's particularly suited to building business applications. This type of application is usually concerned with keeping business records, centered around create, read, update, and delete (CRUD) operations. Not only does Odoo makes it easy to build this type of application, it also provides rich components to create compelling user interfaces, such as kanban, calendar, and graph views.
This book is organized into five parts. We start by providing an overview of the Odoo framework, setting up a development environment, and building our first Odoo application. Being generally familiar with the main Odoo components, we will dive, in more detail, into each of the three main application layers—models, business logic, and views. Finally, our application will need to be deployed to a production environment and maintained. That's what is covered in the final chapter of the book.
In this chapter, we will quickly get into the action, exploring the Odoo internals directly from the web user interface, even before having set up our local development environment.
In this chapter, we will do the following:
- Introduce the learning project used in this chapter, the to-do application.
- Understand the Odoo architecture, editions, and releases, to have the essential context and insights relevant to working with Odoo.
- Prepare a basic Odoo work environment, so that we can work on an example project and learn by experience. Several options are proposed:
- Using Odoo online
- Using the Windows all-in-one installer
- Using Docker
- Enable the developer mode, to make available in the user interface the tools we will be using.
- Modify an existing model to add a field, a quick introduction to a common customization.
- Create a custom data model, to add new data structures for your applications.
- Configure access security, to allow specific user groups to access the application features.
- Create menu items, to make the new data model available in the user interface.
- Create list, form, and search views, the basic building blocks for the user interface.
We will learn by example, and the next section will introduce the project we will use for this.
The minimal requirement for this chapter is to have a modern web browser, such as Firefox, Chrome, or Edge. With this you can follow the chapter using an Odoo SaaS trial database, as explained in the Preparing a basic work environment section.
You may go a little further and use a packaged Odoo distribution to have it locally installed on your computer. For that, you only need an operating system such as Windows, macOS, Debian-based Linux (such as Ubuntu), or Red Hat-based Linux (such as Fedora). Windows, Debian, and Red Hat have installation packages available. Another option is to use Docker, available for all these systems and for macOS. The Preparing a basic work environment section will guide us in any of these installation scenarios.
In this chapter, we will mostly have point-and-click interaction with the user interface. You will find the code snippets used and a summary of the steps performed in the book's code repository, at https://github.com/PacktPublishing/Odoo-12-Development-Essentials-Fourth-Edition, under the ch01
folder.
The TodoMVC (http://todomvc.com/) project provides a comparison between multiple JavaScript frameworks by implementing the same simple to-do application in each of them. Inspired by this, we will go through the experience of building a simple to-do application with Odoo.
It should allow us to add new to-do items, and then mark them as completed. For example, you could add to-do items to the list, such as Buy eggs, and then check an Is Done? box once they are completed. The To-do Items
should be private to the current user, so that you will only be able to access your own to-do items.
This should be enough for a simple to-do application, but to make it a little more interesting we will introduce a couple of complications. Our to-do list items should be able to include a list of people involved in the task, the work team.
It is useful to think about our application by considering several layers involved:
- The data tier: Implemented through models
- The logic tier: Implemented through automation code
- The presentation tier: Implemented through views
For the data tier, we need a To-do Item
model. We will also make use of the built-in partner (or contacts) model to support the work team feature. We must not forget to configure the access control security for our new model.
The logic tier used here will be the basic CRUD operations handled by the framework, and we don't have in our requirements any additional automation to support. To access the full power of the framework, we need to use Python code in developer modules. While we can't do that yet, the developer menu does provide some tools for us to implement some business logic from the user interface, the automate actions. We will work on a simple example of how to use them.
Finally, for the presentation tier we will add the menu option for our application, and the views for the to-do item model. The essential views for a business application are the list view, where we can browse the existing records, and the form view, where we can zoom in to a record and see all the details. For better usability, we can also add preconfigured filters to the search box, available in the list view. The available search options are also considered a view, so this can be done through a search view.
The following are the steps to create a to-do list:
Our specification for the application includes the ability to select a list of people that will be working on the task, so we need a Model to represent people. Fortunately, Odoo includes out of the box a model for this—the partner model (res.partner
is its technical name), used to store individual people, companies, and addresses.
And only particular persons are selectable for this work team. This means that we need to modify the partner model to add this new Is Work Team?
flag.
So, the To-do Items
model should also include the work team field, with a list of people. The linked people are selectable from the partners/contacts that have the Is Work Team?
flag enabled.
As a summary, this is what we will need to do:
Before we go into the actual implementation, we will first discuss a few basic concepts about the Odoo framework, and then learn how to prepare an environment to work with.
It is useful to understand the several layers involved in the Odoo architecture, and the role of each type of component we will use. So we will have a pragmatic overview of the Odoo application architecture, with a focus on helping application development by decomposing work into several components.
Also, Odoo publishes two different product editions, community and enterprise, and regularly releases new versions for both. It is important to understand the differences we can expect between the editions, and what a new major release can mean for our development and deployment. For this, we have an overview of the differences between CE and EE, and on the Odoo major version stability policy.
Let's start looking at the Odoo application architecture.
Odoo follows a multi-tier architecture, and we can identify three main tiers—data, logic, and presentation:
The Data Tier is the lowest-level layer, and is responsible for data storage and persistence. Odoo relies on a PostgreSQL server for this. PostgreSQL is the only supported database server, and this is a design choice. So, other databases such as MySQL are not supported. Binary files, such as attachments of documents or images, are usually stored in the filesystem, in a directory referred to as the filestore
.
Note
This means that a full backup of an Odoo instance needs both a database dump and a copy of the filestore
.
The Logic Tier is responsible for all the interactions with the data layer, and is handled by the Odoo server. As a general rule, the low-level database should only be accessed by this layer, since it is the only way to ensure security access control and data consistency. At the core of the Odoo server, we have the object-relational mapping (ORM) engine for this interface. The ORM provides the application programming interface (API) used by the add-on modules to interact with the data.
For example, the partner data entity, such as a customer or a supplier, is represented in the ORM by a model. This model is a Python object class supporting several interaction methods, such as create()
to create new partner records, or read()
to query existing records and their data. These generic methods can implement specific business logic in particular models. For example, the create()
method might implement default values or enforce validation rules; the read()
method might support some automatically computed fields, or enforce access controls depending on the user performing that action.
The Presentation Tier is responsible for presenting data and interacting with the user. It is implemented by a client responsible for all the user experience. The client interacts with the ORM API to read, write, verify, or perform any other action, calling ORM API methods through remote procedure calls (RPCs). These are sent to the Odoo server for processing, and then the results are sent back to the client for further handling.
For the Presentation Tier, Odoo provides a full-featured web client out of the box. The web client supports all the features needed by a business application: login sessions, navigation menus, data lists, forms, and so on. The global look and feel are not as customizable as a frontend developer might expect, but it makes it easy to create a functional and consistent user experience.
A complementary presentation layer includes the website framework. It gives full flexibility to create web pages with the exact user interface intended, like in other CMS frameworks, at the expense of some additional effort and web expertise. The website framework supports web controllers to implement code for presenting specific logic, keeping it separate from the model's intrinsic logic. Frontend developers will probably feel very much at home in this space.
The Odoo server API is very open, and all server functions are available through it. The server API used by the official web client is the same as the one available to any other application. So, other client implementations are possible, and could be built in almost any platform or programming language. Desktop and smartphone applications can be built to provide specific user interfaces, leveraging the Odoo data and logic tiers for business logic and data persistence.
Odoo is the name of the software product, and also the name of the company that builds it. Odoo follows an open core business model, where the community edition (CE) is free and open source, and the enterprise edition (EE) is a paid product, providing income for the company.
The CE provides all the framework features plus the essential features for most of the business applications bundled with Odoo. It is licensed under an LGPL license, chosen to allow adding proprietary extensions on top of open source modules.
The EE is built on top of the CE, providing all its features plus some additional exclusive ones. Notably, it includes an improved and mobile-friendly user interface, although the user interface underlying the organization is essentially the same in both editions.
The Odoo online SaaS service uses Odoo enterprise, and may have deployed intermediate versions released after the latest Odoo enterprise major version.
At the time of writing, Odoo's latest stable version is version 12, marked on GitHub as branch 12.0. This is the version we will work with throughout the book. In recent years, major stable versions have been released on a yearly schedule, in October, at the annual Odoo experience conference.
The last three stable versions are supported. With the release of 12.0, versions 11.0 and 10.0 are still supported, and version 9.0 stopped being supported. This means it will stop receiving bug and security fixes.
It's important to note that Odoo databases are incompatible between Odoo major versions. If you run an Odoo 11 server against a database created for a previous major version of Odoo, it won't work. Non-trivial migration work is needed before a database can be used with a later version of the product.
The same is true for add-on modules: as a general rule, an add-on module developed for an Odoo major version will not work on other versions. When downloading a community module from the web, make sure it targets the Odoo version you are using.
On the other hand, major releases (10.0, 11.0) are expected to receive frequent updates, but these should be mostly bug fixes. They are assured to be API-stable, meaning that model data structures and view element identifiers will remain stable. This is important because it means there will be no risk of custom modules breaking due to incompatible changes in the upstream core modules.
The version in the master
branch will result in the next major stable version, but until then, it's not API-stable and you should not use it to build custom modules. Doing so is like moving on quicksand—you can't be sure when some changes will be introduced that will break your custom module.
The first thing we need is to have an Odoo instance that we can use for our learning project.
For the purpose of this chapter, we just need a running Odoo instance, and the particular installation method is not relevant. To quickly get up and running, we can use a prepackaged Odoo distribution, or even just use an Odoo SaaS trial database (https://www.odoo.com/).
This can be the simplest way to get started. No need to actually install anything for now, just go to https://www.odoo.com/ and create a free trial database. The Odoo Cloud software as a service (SaaS) is based on the enterprise edition (EE), with additional, exclusive, intermediate version releases. Other than the trial, at the time of writing it also offers a free plan: databases with only one application installed are free to use. The SaaS service runs vanilla Odoo enterprise and custom modules are not allowed. For cases where customizations are needed, the Odoo.sh
service can be used, providing a full-featured development platform to customize and host solutions based on Odoo enterprise. See https://www.odoo.sh/ for more information.
Note
Changes in Odoo 12
In previous Odoo versions, the menu structure of the web client was significantly different between the CE and EE. In Odoo 12, the menus in both editions follow a similar structure.
To create a new database on the Odoo Cloud SaaS, you will probably be asked to select a starting application. No specific application is required to follow this chapter, but if you're unsure on what to pick, customer relationship management (CRM) would be fine.
Also worthy of note is that the EE, on the Odoo SaaS, has the Odoo Studio application builder available. We won't be using it, since it is not available for the CE, which is used as a reference in this book. Odoo Studio provides a user-friendly user interface for the developer features introduced in this chapter, along with a few extra features, such as the ability to export the customizations made in a convenient module package. But the main capabilities are similar to what we can get by using the basic developer mode.
Ready-to-install Odoo packages can be found at https://download.odoo.com, available for any of the currently supported Odoo versions, as well as for the master branch (the latest development version). You can find the Windows (.exe
) installers, alongside the Debian (.deb
) and CentOS (.rpm
) packages.
To install on Windows, find the latest .exe
build in the nightly
directory and install it. The all-in-one installation is straightforward, as it provides all that you will need to run Odoo; Python 3, a PostgreSQL database server, the Odoo server, and all Odoo additional dependencies. A Windows service is also created to automatically start the Odoo and PostgreSQL services when your machine starts.
Docker provides a convenient multi-platform solution to run applications. It can be used to run applications on macOS, Linux, and Windows. The container technology is simple to use and resource-efficient when compared to classic virtual machines.
You must first have Docker installed in your system. The Docker CE is free of charge, and can be downloaded from https://www.docker.com. It's worth referring to Docker's website for the latest installation details.
In particular, keep in mind that virtualization must be enabled in your BIOS setup. Also, the Docker CE for Windows requires Hyper-V, only available in Windows 10 Enterprise or Education releases (see https://docs.docker.com/docker-for-windows/install), and Docker CE for mac requires OS X El Capitan 10.11 and newer macOS releases.
For other Windows and macOS versions, you should instead install Docker Toolbox, available at https://docs.docker.com/toolbox/overview. Docker Toolbox bundles VirtualBox and provides a preconfigured shell that should be used as the command-line environment to operate Docker containers.
The Odoo Docker images are available in the Docker store at https://store.docker.com/images/odoo. There, we can find the versions available, and the basic instructions to get started with them. To run Odoo, we will need two Docker containers, one for the PostgreSQL database, and another for the Odoo server.
The installation and operation is done from a command-line window. To install the PostgreSQL Docker container, run this:
$ docker run -d -e POSTGRES_USER=odoo -e POSTGRES_PASSWORD=odoo --name db postgres:10
It will download the latest PostgreSQL image from the internet, and start a container for it running as a background job.
Next, install and run the Odoo server container, linking it to the PostgreSQL container we just started, and exposing it on port 8069
:
$ docker run -t -p 8069:8069 --name odoo --link db:db odoo:12.0 -d odoo12
With this, you will see the live Odoo server log in your terminal window, and can access the Odoo instance by opening http://localhost:8069
with your favorite web browser.
Note
The Odoo server can fail to start if port 8069
is already in use, for example, by an already running Odoo server. In this case, you might look for and stop the running service (for example, by looking at the list of running services), or try to start this Odoo server on a different port by changing the-p
option. For example, to use port 8070
, use -p 8070:8069
. In that case, you probablyalso want to change-d <dbname>
to set the database name that instance should use.
There are a few basic commands you should know to help manage these Docker containers:
docker stop <name>
stops a containerdocker start <name>
starts a containerdocker start -a <name>
starts a container, and attaches the output, such as the server log, to the terminal windowdocker attach <name>
reattaches a container's output to the current terminal windowdocker ps
lists the current Docker containers
These are the basic commands needed to operate our Docker containers.
In case you get in trouble running the containers, here is a recipe to start over:
$ docker container stop db $ docker container rm db $ docker container stop odoo $ docker container rm odoo
The Docker technology has more potential, and it might be interesting to learn more about it. The Docker website has good learning documentation. A good place to get started is https://www.docker.com/get-started.
It is worth noting that installation packages are also available for Debian-based (such as Ubuntu) and Red Hat-based (such as CentOS and Fedora) Linux systems.
We won't be able to go into much detail on how to install them, but if you are familiar with Debian or Red Hat, this is also an option to consider. The installation packages are available from https://download.odoo.com, and the official documentation provides a good explanation on how to install them at https://www.odoo.com/documentation/master/setup/install.html.
Regarding the source code installation, it is the most complex, but also the most versatile of the installation alternatives, and it will be explained in detail in Chapter 2, Preparing the Development Environment.
By now, we should have a PostgreSQL database server and an Odoo server instance running. We now need to create an Odoo database before we can start working on our project.
If you installed Odoo locally, keeping the default configuration options, the server should be available at http://localhost:8069
. When we access it for the first time, since there are no Odoo databases available yet, we should see an assistant to create a new database:
The information you need to provide is the following:
- The
Database Name
is the identifier name to use for this database. You can have several databases available on the same server. Email
is the login username to use for the special Administrator super user. It doesn't have to be an actual email address.Password
is your secret password to log in as the Administrator.Language
is the default language to use for the database.Country
is the country set in the database's company data. It is optional, and is relevant for localization features in some apps, such as Invoicing and Accounting.- The load demonstration data checkbox allows you to create the database with demonstration data, instead of creating a clean database. This is usually desirable for development and test environments.
A master password field might also be asked for, if one was set in the Odoo server configuration. This allows you to prevent unauthorized people from performing these administrative tasks. But by default it is not set, so you probably won't be asked for it.
After pushing the create database button, the new database will be bootstrapped, a process that can take a couple of minutes, and once ready you are redirected to the login screen.
The login screen has a manage databases link at the bottom to access the database manager. There, you can see the list of available databases; back up, duplicate, or delete them; and also create new ones. It can also be directly accessed at http://localhost:8069/web/database/manager
.
Note
The database manager allows for privileged administration operations, and by default is enabled and unprotected. While it is a convenient feature for development, it can be a security risk for databases that have real data, even if they are test or development environments. Consider setting a strong master password, or even better, disabling it. This is done by setting list_db = False
in the server configuration file.
Now that we have an Odoo instance and a database to work with, the next step is to enable the developer mode, providing the tools we need to implement our project.
To implement our project, we need the tools provided by the developer mode, which needs to be enabled.
The developer mode allows us to customize Odoo apps directly from the user interface. This has the advantage of being a rather quick way to make changes and add features. It can be used from small modifications, such as adding a field, to larger customizations, such as creating an application with several models, views, and menu items.
These customizations done directly from the user interface have some limitations, when compared to the customizations done with programming tools, covered throughout the rest of the book. For example, you can't add or extend the default ORM methods (although in some cases automated actions can be enough to provide an alternative to that). They also can't be easily integrated into a structured development workflow, which typically involves version control, automated tests, and deploying into several environments, such as quality assurance, pre-production, and production.
Here, we will be using the developer mode features mainly as a way to introduce how application configuration data is organized in the Odoo framework, and how the developer mode can be leveraged for simple customizations, or to quickly outline or prototype the solution to implement.
To enable the developer mode, go to Settings
| Dashboard
, and in the lower-right corner you should find the Activate the developer mode
link. Clicking on it enables the developer mode features for this browser window. For Odoo 9.0 and before, the developer mode is activated in the About
dialog window, available from the User menu, in the upper-right corner of the web client.
We also have available an Activate the developer mode (with assets)
option. What it does is prevent web client asset minification. It is useful to debug the web client itself, at the expense of making the navigation a little slower.
For faster load times, the web client minifies the JavaScript and CSS assets into compact files. Unfortunately, that makes web client debugging nearly impossible. The Activate the developer mode (with assets)
option prevents this minification and loads the web assets in individual, non-minified files.
The developer mode can also be enabled by tinkering directly with the current URL, so that you don't have to leave your current screen to open settings. Edit the URL to change the .../web#...
part to insert .../web?debug#...
or .../web?debug=assets#...
. For example, http://localhost:8069/web#home
would be changed to http://localhost_8069/web?debug#home
.
Although there is no link to enable it, the frontend framework also supports the debug flag. To disable asset minification in a frontend web page, add ?debug=assets
to the corresponding URL. Take note that the option will probably not persist when navigating through links to other frontend pages.
Note
There are browser extensions available for both Firefox and Chrome that provide a convenient button to enable and disable the developer mode. Look for "Odoo debug" in Firefox add-ons or the Chrome store.
Once the developer mode is enabled, we will see two additional menus available:
- The
Developer Tools
menu, the bug icon on the right-hand side of the top menu bar, just before the username and avatar - The
Technical
menu item, in theSettings
application
The following screenshot shows the two additional menus:
The developer mode also enables additional information on form fields; when pausing the mouse pointer over a field, a tooltip will display technical information on it.
We will be using the most relevant developer mode features in the next sections.
Adding a custom field to an existing form is a common customization, and it can be done from the user interface, without the need to create a custom module.
For our to-do application, we want to select a group of people that will be able to collaborate on to-do items. We will identify them by setting a flag on their partner form. For that, we will add an Is Work Team?
flag to the partner model.
The partner model is part of the Odoo core, and is available even if you haven't installed any apps yet. However, you may not have a menu option available to visit it. A simple way to add one is to install the Contacts
application. Open the Apps
top menu, look up this application, and install it, if you have not already done so:
After this, the Contacts
application top menu option will be available.
To visit a Model's definition, with the developer mode enabled, in the Settings
application go to the Technical
| Database Structure
| Models
menu item.
Look up the Model
having res.partner
. The corresponding Model Description
should be Contact
. Click on it to open the form view, and you will see all the specific details about the partner model, including the field list:
Now, Edit
the form and click on the Add a line
button at the bottom of the Fields
list. A pop-up window will be presented for new field creation.
Let's fill in the configuration:
Field Name
:x_is_work_team
Field Label
:Is Work Team?
Field Type
:b
oolean
The Field Name
must start with x_
. This is mandatory for Models
and Fields
created directly through the user interface. Customizations made through add-on modules don't have this limitation.
That's it. Click save and close, and our new field should have been added to the Fields
list. Chances are that this model has more than 80 fields, and so you might need to navigate to the next page of the Fields
list to see it. To do so, use the right arrow in the upper-left corner of the Fields
list.
Now, click on the upper-left save button to make this change permanent.
Our new field is now available in the partners model, but it is not yet visible to users. For that, we need to add it to the corresponding views.
Still on the Model
havingres.partner
form, click on the Views
tab, and we will be able to see all the view definitions for the model. As you can see, each view is a record in the database. Changing or adding view records is immediately effective, and will be visible the next time that view is reloaded:
There are a few important things to note in the Views
list.
We can see that there are several View Type
, such as Form
, Tree
, Search,
or Kanban
. The Search
views are actually definitions of the filters available in the upper-right search box. The other view types are the different ways the data can be displayed. The basic ones are Tree
, for list views, and Form
, for the detailed form view.
Note
Both Tree and List can be used to refer to the same view type. They are in fact lists, and the Tree
name exists for historical reasons—in the past, list views used to have a tree hierarchical mode.
You will notice that the same view type can have several definitions. If you sort the list by View Type,
that will be clear.
Each view type, such as Form
, can have one or more base view definitions (the ones with an empty Inherited View
field). Window Actions
, used by menu items, can specify the particular base view to use. If none are defined, the one with the lowest Sequence
is used. You can think of it as being the default view. Clicking on a views line, we will see a form with the view's details, including the Sequence
value:
And each base view may have extensions, called Inherited Views
. Each of these add incremental changes to the corresponding Base view
, for example, adding a field to an existing form.
Note
Extension views can themselves be extended by other extension views. In this case, the later extension is applied to the Base view
after all preceding extensions have already been applied to it.
The res.partner
model in particular can have a crowded view definitions list, since, like ours, many apps need to add extensions to it. An alternative is to access the particular view we want to extend, and edit it from there using the Developer Tools
menu. This can also be used to learn what specific view is being used somewhere in the user interface.
Let's try it now:
- Click on the
Contacts
application to be presented with a list of contact cards, then click on any of the cards, we will navigate to the correspondingForm
view:
- On the
Form
view, click on theDeveloper Tools
menu (the bug icon in the upper-right corner) and select theEdit View: Form
option. This will show the same view details form we saw before inModels
, but positioned on the actual base view definition used here. As you can see, it is theres.partner.form
view. We can see the owner module through theExternal ID
field. In this case, it isbase.view_partner_form
, so we know that this view belongs to thebase
module. In theArchitecture
field, we can see the XML with the baseviewdefinition. We could simply edit the view architecture to add our new field, but in the long run it is not a good idea: this view is owned by an add-on module, and if some time in the future that module is upgraded, these customizations will be overwritten and lost. The proper way to modify a view is to create anInherited View
extension:
- Using the
Inherited Views
tab, we should now create an extension view to add elements to theBase view
:- First, we need to pick an element from the original view to use as the extension point. We can do that by inspecting the
Architecture
inBase view
and choosing an XML element with aname
attribute. Most of the time, this will be a<field>
element. Here, we will pick the<field name="category_id" ...>
element:
- First, we need to pick an element from the original view to use as the extension point. We can do that by inspecting the
- Now, open the
Developer Tools
menu, click on theEdit View: Form
option, select theInherited Views
tab, and click onAdd a line
at the bottom of the list. - A pop-up window,
Create Views which inherit from this one,
will be shown, and we should fill it with the following values:
- Now, open the
View Name
:Contacts - Custom "Is Work Team" flag
Architecture
: Use the following XML:
<field name="category_id" position="after"> <field name="x_is_work_team" /> </field>
- The other important fields, such as the
Model
,View Type,
andInherited View
, already have the correct default values
- The other important fields, such as the
- We can now
Save & Close
, then, in theEdit View: Form
window, clickSave
, and finally close it.
We will be able to see the change done once we reload the Contacts
form view. This means reloading the page in your web browser. In most browsers, you can do that by pressing F5.
If we now visit again a contact form, we should see the new field on the left-hand side, below the Tags
field:
Models are the basic components for applications, providing the data structures and storage to be used. Next, we will create the Model for the To-do Items
. It will have three fields:
- Description
-
Is done?
flag - Work team partner list
As we have seen earlier, Model definitions are accessed in the Settings
app, in the Technical
| Database Structure
| Models
menu.
To create a Model, follow these steps:
- Visit the
Models
menu, and click on the upper-leftCreate
button. Fill in the new Model form with these values:
Model Description
:To-do Item
Model
:x_todo_item
We should save it before we can properly add new fields to it.
- So, click on
Save
and thenEdit
it again. You can see that a few fields were automatically added. The ORM includes them in allModels
, and they can be useful for audit purposes:
The x_name
(or Name
) field is a title representing the record in lists or when it is referenced in other records. It makes sense to use it for the To-do Item
title. You may edit it and change the Field Label
to a more meaningful label description.
Adding the Is Done?
flag to the Model should be straightforward now.
- In the
Fields
list, click onAdd a line
, at the bottom of the list, to create a new field with these values:
Field Name
:x_is_done
Field Label
:Is Done?
Field Type
:boolean
The new Fields
form should look like this:
Now, something a little more challenging is to add the Work Team
selection. Not only it is a relation field, referring to a record in the res.partner
Model, it also is a multiple-value selection field. In many frameworks this is not a trivial task, but fortunately that's not the case in Odoo, because it supports many-to-many relations. This is the case because one to-do can have many people, and each person can participate in many to-do items.
- In the
Fields
list, click again onAdd a line
to create the new field:
Field Name
:x_work_team_ids
Field Label
:Work Team
Field Type
:many2many
Object Relation
:res.partner
Domain
:[('x_is_work_team', '=', True)]
The many-to-many field has a few specific definitions—Relation Table
, Column 1,
and Column 2
fields. These are automatically filled out for you and the defaults are good for most cases, so we don't need to worry about them now. These will be discussed in more detail in Chapter 6, Models – Structuring the Application Data.
The domain attribute is optional, but we used it so that only eligible work team members are selectable from the list. Otherwise, all partners would be available for selection.
The Domain
expression defines a filter for the records to be presented. It follows an Odoo-specific syntax—it is a list of triplets, where each triplet is a filter condition, indicating the Field Name
to filter, the filter operator to use, and the value to filter against. A detailed explanation of domain expressions is given in Chapter 7, Recordsets – Working with Model Data.
Note
Odoo has an interactive domain filter wizard that can be used as a helper to generate Domain expressions. You can use it at Settings | User Interface | User-defined Filters
. Once a target Model
is selected in the form, the Domain
field will display an add filter button, which can be used to add filter conditions, and the text box below it will dynamically show the corresponding Domain expression code.
We now have the underlying Model for our to-do app, but we still don't have access to it. After creating a Model, we need to configure the groups that can access it. We will do that next.
Odoo includes built-in access control mechanisms. A user will only be able to use the features he was granted access to. This means that the library features we created are not accessible by regular users, even the admin user.
Note
Changes in Odoo 12
The admin user is now subject to access control like all other users. In previous Odoo versions, the admin
user was special, and bypassed security rules. This is no longer true, and we need to grant access privileges to be able to access Model data.
The central pieces for access security are the security groups, where the access rules are defined. Access for each user will depend on the groups he belongs to. For our project, we will create a to-do user group, to be assigned to the users we want to have access to this feature.
We give a group read or write access to particular Models
using ACL. For our project, we need to add read and write access to the newly created to-do item model.
Furthermore, we can also set access rules for the record ranges users can access in a particular Model. For our project, we want the T
o-do Items
to be private for each user, so to-do users should only be able to access the records created by themselves. This is done using the security record rules.
Access control is based on groups. A security group is given access to Models
, and this will determine the menu items available to the users belonging to that group. For more fine-grained control, we can also give access to specific menu Items, views, fields, and even data records (with Record Rules
).
The security groups are also organized around apps, and typically each app provides at least two groups: Users
, capable of performing the daily tasks, and Manager
, able to perform all configurations for that app.
Let's create a new security group. In the Settings
top menu, navigate to Users & Companies
| Groups
. Create a new record using the following values:
Application
: Leave emptyName
:To-do User
Inherited
tab: Add theUser types / Internal User
item
This is how it should look like:
The to-do app is not available yet in the Application
selection list, so we added it directly from the Group
form.
We also made it inherit the Internal User
group. This means that members of this group will also be made members of the Inherited
groups (recursively), effectively having the permissions granted to all of them. Internal User
is the basic access group, and app security groups usually inherit it.
Now, we can grant access to specific Models
to the Group /
To-do User
. We can use the Access Rights
tab of the Groups
form for this. Add an item there, using these values:
Name
:To-do Item User Access
Object
: SelectTo-do Item
from the listRead Access
,Write Access
,Create Access
, andD
elete Access
: Checked
Model access can also be managed from the Technical
| Security
| Access Rights
menu item.
We don't need to add access to the Partner
Model because the Group
is inheriting the Internal Users
group, which already has access to it.
We can now try these new security settings, by adding our admin
user to this new Group
:
- Select the
Users & Companies
|Users
menu item, select theMitchell Admin
user from the list, andEdit
the form:
- In the
Access Rights
tab, in theOther
section, we can see aTo-do User
checkbox to enable the security group for this user. Select it, andSave
the form.
If everything was done correctly, you should be able to see the to-do top menu; use it to add to-do items. We should see only our own items and won't be able to access other users'.
When given access to a Model, by default users will be able to access all its records. But in some cases, we need to restrict the particular records each user should be able to access. This is possible using record rules, which define domain filters to automatically be enforced when performing read or write operations.
For example, in our to-do app, the To-do Items
are expected to be private, so we want users to only be able to see their own items. We need a record rule to filter only the records created by the current user:
- The
create_uid
field is automatically added by the framework, and stores the user that created the record, and we can use it to see who owns each record - The current user is available in the
user
variable, auser
variable browse object available in the context where thedomain
filter is evaluated
We can use this in a domain
expression to achieve our goal: [('create_uid', '=', user.id)]
.
Record rules are available in the Settings | Technical | Security | Record Rules
menu. Navigate there and create a new Record Rules
, with the following values:
Name
: A descriptive title, such asTo-do Own Items
Object
: Select the Model from the list,To-do Item
in our caseAccess Rights
: The actions where the rule will be applied; leave all checkedRule Definition
: TheDomain Filter
,[('create_uid', '=', user.id)]
Groups
: The security groups it applies to; select and add theTo-do User
group
This is how the Record Rules
definition will look like:
And we're done. You can now try this new rule by creating a couple of to-do items with both the Admin
and Demo
users. Each should be able to see only their own items. The Record Rules
can be switched off through the box button in the upper-right corner of the form. If you try that and check the to-do item list, you should see all the items from all users.
In previous Odoo versions, the admin
user was special and bypassed access security. In version 12 this has changed, and the admin
account belongs to all app security groups, but is a regular user. We still have a superuser that bypasses access security, but it doesn't have a login.
We can still work as a superuser. When logged in as a user with the Admin \ Setting
group, the Become Superuser
option is in the developer menu, Or, use the Login as superuser
hidden option in the login screen, visible if the Developer mode is enabled.
When the superuser is enabled, in the upper-right corner the current user is shown as OdooBot, and the colors in the upper-right area change to yellow and black stripes, to make it clear the superuser is enabled.
This should be used only if absolutely necessary. The fact that the superuser bypasses access security can lead to data inconsistencies, for example in a multi-company context, and should be avoided.
We now have a Model to store the To-do Items
, and want to have it available in the user interface. Adding a menu item will achieve that.
We will create a top-level menu item that directly opens the to-do list. Some apps, such as Contacts
, can work like this, but others have submenu items, shown in the top bar.
Note
Changes in Odoo 12
In the community edition, the menu items below the first level are now shown in the top bar, like in the EE. In previous versions, the CE presented these menu items on the left-hand side of the screen.
Menu definitions are in the Settings
application, in Technical | User Interface | Menu Items
:
Create a new menu item using the following values:
Menu
:To-do
Parent Menu
: (empty)- In the
Action
field, selectir.actions.act_window
, and in the selection list on the right, clickCreate and Edit
to open a form for the relatedWindow Actions
- Set the following values on the
Window Actions
form:Action name
:To-do Items
Object
:x_todo_item
(the technical name of the target Model)
At this point the Action definition should look like this:
To see changes in the menu, we need to reload the web client. In most browsers, you can use the F5 key for this. We can now use this menu item to access and interact with the to-do items model. We haven't created any view for it yet, but the Odoo framework is nice enough to automatically generate some basic views for us:
In our case, an action was added directly to a top-level menu item, with no child menu items. But menus can be a tree of menu items, with parent/child relations. The leaf menu items have a related Action
, defining what happens when it is selected. This Action Name
is what will be used as the title of the presented views.
There are several Action Type
available, and the most important ones are window, reports, and server actions. Window Actions
are the most frequent ones, and are used to present views in the web client. Report actions are used to run reports and server actions are used to define automated tasks.
At this point, we are concerned with Window Actions
that are used to display views. The Menu Item we just created for the to-do item uses a Window Actions
, which was created directly from the Menu Item form. We can also view and edit it from the Settings
| Technical
| Actions
menu options. In this particular case, we are interested in the Window Actions
menu option.
Note
In many cases, it is more convenient to use the Edit Action
option in the Developer Tools
, providing a convenient shortcut to edit the Window Actions
that was used to access the current view.
Now we want to create our views, so that's what we will be working on in the next section.
We have created the To-do Items
Model and made it available in the user interface with a Menu Item. Next, we will be creating the two essential views for it—a list (also called a tree
) and a form.
We will now create a list view:
View Name
:To-do List View
View Type
:Tree
Model
:x_todo_item
This is how the View definition is expected to look like:
- In the
Architecture
tab, we should write XML with the view structure. Use the following XML code:
<tree> <field name="x_name" /> <field name="x_is_done" /> </tree>
The basic structure of a list view is quite simple—a <tree>
element containing one or more <field>
elements for each of the columns to display in the list view.
We can do a few more interesting things with list views, and will explore them in more detail in Chapter 10, Backend Views – Design the User Interface.
Next, we will create the form view:
View Name:
To-do Form View
View Type
:Form
Model
:x_todo_item
- In the
Architecture
tab, type the following XML code:
<form> <group> <field name="x_name" /> <field name="x_is_done" /> <field name="x_work_team_ids" widget="many2many_tags" context="{'default_x_is_work_team': True}" /> </group> </form>
The form view structure has a root <form>
element, containing elements such as <field>
, among others that we will learn about in Chapter 10, Backend Views – Design the User Interface. Here, we also chose a specific widget for the work team field, to be displayed as tag buttons instead of a list grid.
We added the widget
attribute to the Work Team field, to have the team members presented as button-like tags.
By default, relational fields allow you to directly create a new record to be used in the relationship. This means that we are allowed to create new Partner
directly from the Work Team
field. But if we do so, they won't have the Is Work Team?
flag enabled, which can cause inconsistencies.
For a better user experience, we can have this flag set by default for these cases. This is done with the context
attribute, used to pass session information to the next View, such as default values to be used. This will be discussed in detail in later chapters, and for now we just need to know that it is a dictionary of key-value pairs. Values prefixed with default_
provide the default value for the corresponding field.
So in our case, the expression needed to set a default value for the partner's Is Work Team?
flag is {'default_x_is_work_team': True}
.
That's it. If we now try the To-Do
menu option, and create a new item or open an existing one from the list, we will see the form we just added.
We can also make predefined filter and grouping options available, in the search box in the upper-right corner of the list view. Odoo considers these view elements also, and so they are defined in Views
records, just like lists and forms are.
As you may already know by now, Views
can be edited either in the Settings
| Technical | User Interface
menu, or from the contextual Developer Tools
menu. Let's go for the latter now; navigate to the to-do list, click on the Developer Tools
icon in the upper-right corner, and select Edit Search view
from the available options:
Since no search view is yet defined for the To-do Items
Model, we will see an empty form, inviting us to create the first one. Fill in these values and save it:
View Name
: Some meaningful description, such asTo-do Items Filter
View Type
:Search
Model
:x_todo_item
Architecture
: Add this XML code:
<search> <filter name="item_not_done" string="Not Done" domain="[('x_is_done', '=', False)]" /> </search>
If we now open the to-do list from the menu, so that it is reloaded, we will see that our predefined filter is now available from the Filters button below the search box. If we type Not Done
inside the search box, it will also show a suggested selection.
It would be nice to have this filter enabled by default, and disable it when needed. Just like default field values, we can also use context
to set default filters.
When we click on the To-do
menu option, it runs a Window Actions
to open the To-do list view. This Window Actions
can set a context value, signaling the Views
to enable a search filter by default. Let's try this:
The Domain
allows to set a fixed filter on the records shown, which can't be removed by the user. We don't want to use that. Instead, we want to enable the item_not_done
filter created before by default, which can be deselected whenever the user wishes to. To enable a filter by default, add a context key with its name prefixed withsearch_default_
, in this case {'search_default_item_not_done': True}
.
If we click on the To-do
menu option now, we should see the Not Done
filter enabled by default on the search box.
In this chapter, not only did we present an overview of how Odoo components are organized, but we also made use of the developer mode to dive into the Odoo internals and understand how these components work together to create applications.
We used these tools to build a simple application, with Models, Views, and the corresponding Menu. We also learned the usefulness of the Developer Tools
to inspect existing applications or make quick customizations directly from the user interface.
In the next chapter, we will start getting more serious about Odoo development, and will learn to set up and organize our development environment.
- What are the relevant layers to consider when designing an Odoo application?
- How is the developer mode enabled?
- Where do you create a new data model?
- How do you make a new data model available for end users to create and edit records?
- How do you add a field to an existing form?
- What is a domain, and where can it be used?
- How can you set default values on the form you are navigating to?
- How do you give a user access to a model?
- How can you add a Category field to the To-do Items, with possible values selectable from an options list? (The options list is editable and can be expanded by users).
- How can you extend the to-do category model, so that the list of categories is specific for each user?