$ ./odoo-bin shell \
-c /etc/odoo.conf \
--xmlrpc-port=8888 \
--longpolling-port=8899 \
-d odoo
In Odoo, you have the ability to run Odoo as a web server and access it via a GUI, but you can also run a python REPL with all of the Odoo modules loaded in as globals. This is extremely helpful for debugging and for learning.
For example, you could start up the shell, query for information via env/search/browse commands, run individual functions, access variables and properties associated with core classes, load in new functions if needed for testing, etc.
How to run an Odoo shell
Let’s break down the command:
$ ./odoo-bin shell \
-c /etc/odoo.conf \
--xmlrpc-port=8888 \
--longpolling-port=8899 \
-d odoo
./odoo-bin shell
odoo-bin
is the executable in the root directory of the core Odoo project. This is how you run
an Odoo instance.
If you run odoo-bin help
you will see that we have a few different commands that we can run.
One of those commands is shell
which will start up our REPL.
odoo:$ ./odoo-bin help
Available commands:
deploy Deploy a module on an Odoo instance
help Display the list of available commands
scaffold Generates an Odoo module skeleton
server Start the odoo server (default command)
shell Start odoo in an interactive shell
start Quick start the Odoo server for your project
Use 'odoo-bin <command> --help' for individual command help
-c /etc/odoo.conf
Reference to your configuration files, if relevant. If you do not need all of your configurations and addons referenced then you can leave this off.
--xmlrpc-port=8888 --longpolling-port=8899
More optional flags. I use these because then I can run a standard Odoo instance on 8069/8072, but run a shell prompt at the same time on separate non-conflicting ports. You can use any open ports that you would like.
-d odoo
The database that you want to connect to. All Odoo shell prompts are connected to a single database at a time.
What do you have reference to?
Once you got a shell prompt up and running, then check out what you actually have reference to. You can
see this by runnng globals()
:
Here are some of the globals that I end up using the most often:
self
In [1]: self
Out[1]: res.users(1,)
self
is a reference to the currently logged in user. By default, this is going to be id=1 (the
admin user.)
env
A global reference to the Environment
similar to if you would access it via
self.env
.
This is where we can start querying/accessing different data in the system:
In [1]: attachments = env["ir.attachment"].search([])
In [2]: attachments
Out[2]: ir.attachment(356, 355, 354, 353, 352)
odoo / openerp
The global reference to the odoo core. Anything that you would typically import in modules is accessible.
So if you need to access odoo.models
, odoo.tools
,
odoo.exceptions
, etc. you can import or reference those in the shell prompt.
In [1]: f = odoo.fields.Many2one
In [2]: dir(f)
Out[12]:
['__class__',
'__delattr__',
'__dir__',
'__doc__',
'__eq__',
... ]
Some Tricks
Here are just a couple of quick tricks that I use pretty often within the odoo shell.
General Imports
Just like any ipython prompt, you can import any accessible library. This is extremely helpful as you start debugging. Bring different libraries into the prompt.
In [1]: import math, string, io
Viewing Properties and Functions
At the beginning of this article, I said that the shell is great for both debugging and learning. Seeing the properties and functions available helped me initially learn how Odoo worked internally.
You can go through everything available to you via the global odoo
or
env
module.
Let’s take the search
method for example. This is something that many odoo developers use via
commands like env['my.model'].search
. But we can see a quick description of this
directly in the prompt by using ??
:
Above, we are assuming that we already know that the search
method exists. If we actually need
to find methods then we can hit tab at the end of a variable to see all available properties and methods:
Committing Data
Be careful with this since it actually writes to your database.
If you need to update some record via the odoo shell, you have to run the update
method like you would in a standard custom module, but then you have to manually commit them to the database
via env.cr.commit
.
In [1]: users = env["res.users"].search([])
In [2]: for user in users:
...: user.update({"create_uid": 1})
...:
In [3]: env.cr.commit()
Thanks For Reading
I appreciate you taking the time to read any of my articles. I hope it has helped you out in some way. If you're looking for more ramblings, take a look at theentire catalog of articles I've written. Give me a follow on Twitter or Github to see what else I've got going on. Feel free to reach out if you want to talk!