Odoo development cheatsheet
Datetime & Timezones
- All datetime are stored in UTC in database
fields.Datetimeare in UTC. They are only displayed in the user's timezone
Fetching data with specific timezone
This is tricky. If for whatever reason the datetime value cannot be send directly from the UI (and so be automatically converted), the value has to be converted in the code.
import pytz
## Get the timezone first. This is retrieved from context then user, then default. Can be set in another way
timezone = pytz.timezone(self.env.context.get('tz') or self.env.user.tz or 'UTC')
## Create a localized datetime from the date source
date_tz = timezone.localize(fields.Datetime.from_string("1988-05-16 16:55:00"))
## Now get an UTC datetime from the localized one
start = date_tz.astimezone(pytz.timezone('UTC'))
## If needed, set up an end date from the starting one
end = start + relativedelta(years=36)
# Retrieve the data
awesome_guy_ids = self.env['sale.report'].search(['&',
('date', '>=', start),
('date', '<', end),
])
Display date on context timezome
If for whatever reason (reports, typically), the date is displayed in UTC instead of the contaxt timezone, use :
fields.Datetime.context_timestamp(self, date)
Command line interface
You can get the cli with the command odoo shell . From there, it is possible to manipulate odoo objects and use the env variable. This can be very useful for debugging, or sometimes to manipulate data.
In case you want your data manipulation to be persisted, you need to commit with env.cr.commit()
WARNING : This is likely to have consequences. It is not recommended to do such operation in production.
An example :
users = env['res.user'].browse([1,2,3]) #fetch problematic users
users.unlink() #delete them
env.cr.commit() #needed to
View behavior depending to current user's group
It is not possible to access env, user or similar vars in ir.view records. To get different field behaviors depending on current user's group, you need to register several ir.view records (potentially inheriting the previous one) and use the ir.view field groups_id to limit the record to specific groups. Example :
<!-- Switch a field readonly for everyone -->
<record id="view_account_payment_register_form" model="ir.ui.view">
<field name="name">account.payment.register.form.inherit.perp</field></field>
<field name="model">account.payment.register</field>
<field name="inherit_id" ref="account.view_account_payment_register_form"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='payment_date']" position="attributes">
<attribute name="readonly">1</attribute>
</xpath>
</field>
</record>
<!-- Same field is not readonly for admin though -->
<record id="view_account_payment_register_form_admin" model="ir.ui.view">
<field name="name">account.payment.register.form.inherit.perp.admin</field>
<field name="model">account.payment.register</field>
<field name="inherit_id" ref="account.view_account_payment_register_form"/>
<field name="groups_id" eval="[(4, ref('base.group_system'))]"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='payment_date']" position="attributes">
<attribute name="readonly">0</attribute>
</xpath>
</field>
</record>
Hide product's Internal Reference
Use the context display_default_code=False. This can be achieved on multiple levels (model field, view, action...)
Customise search & quick search
Inherit name_search function on the related model. To customise from a specific view/action/model, add a context to check on name_search to rewrite the search results To avoid huge load on db, limit results to 8 as the quick search only display 8 results.