- Module structure and manifest
- ORM: models, fields, and relations
- Computed fields and constraints
- View types and inheritance
- Security: access rights and record rules
- Controllers and QWeb
Module Structure Questions
What is the purpose of __manifest__.py in an Odoo module?
It declares the module's metadata — name, version, author, description — and its dependencies (depends), data files to load (data), and asset files (assets). Odoo reads this file to determine load order and whether dependencies are satisfied before installing the module.
What's the difference between 'data' and 'demo' in the manifest?
data files are always loaded — on install and on upgrade. They contain production data like security rules, menus, and views. demo files are loaded only when the database is created with demo data enabled; they contain sample records for learning and testing purposes.
What does noupdate="1" on an XML record mean?
It means the record is loaded only on the first install and never updated on subsequent upgrades — even if the XML changes. Use it for default data that users are expected to customize (e.g., a default email template). Without it, every upgrade would overwrite user modifications.
ORM and Model Questions
What are the three types of model inheritance in Odoo?
Classical (extension): _inherit = 'existing.model' without _name — extends the existing model in-place, adding fields and methods. Prototype (copy): _inherit = 'existing.model' with a new _name — creates a new model that copies the parent's structure. Delegation: _inherits = {'parent.model': 'field_id'} — the child stores parent fields by reference via a Many2one, with field access delegated transparently.
What is the difference between Many2one, One2many, and Many2many?
Many2one: many records point to one parent (FK column in the child table). One2many: the inverse of Many2one — no column in the parent, the child has the FK. Many2many: many-to-many via a join table. Many2one stores a value; One2many is a virtual field; Many2many creates an intermediate table.
When would you use a stored computed field vs a non-stored one?
Use store=True when: the field is read frequently, the computation is expensive, or you need to search/filter on the field. The value is computed on write and stored in a DB column. Use non-stored (default) when: the field is rarely read, it's purely for UI display, or the computation is trivial. Non-stored fields recompute on every read.
What is the difference between @api.constrains and _sql_constraints?
@api.constrains('field1', 'field2') runs Python code on write — use for complex cross-field validations. It runs in memory and can call the ORM. _sql_constraints creates a PostgreSQL constraint (UNIQUE, CHECK) — enforced at the database level, faster, applies even on direct SQL writes, but limited to what SQL supports.
What is sudo() and when should you use it?
sudo() returns a recordset with superuser privileges — it bypasses access rights and record rules. Use it when: you need to read/write records that the current user doesn't have access to by design (e.g., portal users creating records). Never use sudo() without first validating that the current user has the right to trigger that action.
Security Questions
What is the difference between ir.model.access.csv and ir.rule?
ir.model.access.csv controls model-level permissions: which groups can create/read/write/delete records of a model at all. ir.rule controls row-level access: which specific records a user can see, filtered by a domain. Access rights are checked first; if they pass, record rules apply.
What are global record rules vs group-specific record rules?
Global rules (no group assigned) apply to everyone — they are AND-combined with any group-specific rules. Group-specific rules apply only to members of the specified group — multiple group rules for the same model are OR-combined for a user who belongs to multiple groups. This design lets you expand access for admins by adding an allow-all group rule.
View and QWeb Questions
How does XPath inheritance work in Odoo views?
A view with inherit_id extends the parent view. XPath expressions locate elements in the parent; the position attribute controls how the new content is inserted: before, after, inside (append children), replace, or attributes (modify existing attributes). Multiple modules can inherit the same view — Odoo applies them in sequence based on module load order.
What is the difference between t-field, t-out, and t-esc in QWeb?
t-field renders an Odoo model field with widget formatting (dates, currencies, m2o names) and enables inline editing in the website editor. t-out renders a Python expression as raw HTML — use for fields.Html content. t-esc renders a Python expression as escaped plain text — safe for user-supplied strings.
- Be able to write a model with all field types from memory
- Know the three inheritance types and when to use each
- Understand the security layers: groups → access rights → record rules
- Be ready to explain stored vs non-stored computed fields with examples