Skip to Content

Odoo Module Development: Understanding Models, Views and Security Rules

November 13, 2026 by
Odoo Module Development: Understanding Models, Views and Security Rules
Sales

Odoo Module Development: Understanding Models, Views and Security Rules

Odoo's modular architecture is one of the main reasons businesses choose it as their ERP platform. Instead of modifying the entire system whenever a business needs new functionality, developers can create custom modules that extend existing Odoo applications or introduce completely new features.

Three components are especially important in Odoo module development:

  • Models — define data and business logic
  • Views — define how users interact with the data
  • Security Rules — control who can access which records and operations

Understanding how these three components work together is essential for building secure, maintainable, and upgrade-friendly Odoo customizations.

What Is an Odoo Module?

An Odoo module is a structured package that adds functionality to an Odoo database.

A module can introduce:

  • New business models
  • New fields
  • Forms and list views
  • Menus and actions
  • Business workflows
  • Reports
  • Automated processes
  • Access rights
  • Record rules
  • Website features
  • API integrations
  • Custom frontend functionality

For example, a company may want a Customer Credit Approval feature that is not available in its standard Odoo configuration.

A custom module could introduce:

Customer Credit Approval
        ↓
Credit Review
        ↓
Manager Approval
        ↓
Approved / Rejected

The module could contain a new model, user interface, workflow logic, and security configuration.

The Three Core Components of an Odoo Module

At a high level:

             Odoo Custom Module
                    │
        ┌───────────┼───────────┐
        ↓           ↓           ↓
     Models       Views      Security
        │           │           │
      Data       User UI    Permissions
        │           │           │
        └───────────┼───────────┘
                    ↓
             Business Workflow

These components work together.

For example:

Model defines a Purchase Approval record.

View provides the form where users create and review the record.

Security determines which users can create, read, approve, or delete it.

1. Understanding Odoo Models

A model represents a business object in Odoo.

Examples of standard Odoo models include:

res.partner       → Customers / Contacts
sale.order        → Sales Orders
purchase.order    → Purchase Orders
stock.picking     → Inventory Transfers
account.move      → Accounting Documents
mrp.production    → Manufacturing Orders

Custom modules can create their own models.

For example:

from odoo import models, fieldsclass CreditApproval(models.Model):    _name = 'credit.approval'    _description = 'Customer Credit Approval'    name = fields.Char(        string='Reference',        required=True    )    customer_id = fields.Many2one(        'res.partner',        string='Customer',        required=True    )    amount = fields.Float(        string='Credit Limit'    )    state = fields.Selection(        [            ('draft', 'Draft'),            ('submitted', 'Submitted'),            ('approved', 'Approved'),            ('rejected', 'Rejected'),        ],        default='draft'    )

This model creates the foundation for the business functionality.

What Does a Model Define?

A model can define:

Fields

Examples:

  • Text
  • Integer
  • Float
  • Boolean
  • Date
  • Datetime
  • Selection
  • Many2one
  • One2many
  • Many2many

Business Logic

Python methods can define what happens when users perform actions.

Relationships

Models can connect with other Odoo models.

Constraints

Developers can prevent invalid business data.

Computed Values

Fields can automatically calculate values based on other fields.

Common Odoo Field Types

Char

Used for short text.

name = fields.Char(    string='Name')

Examples:

  • Reference number
  • Customer code
  • Serial number

Text

Used for longer text.

notes = fields.Text(    string='Notes')

Useful for:

  • Internal notes
  • Descriptions
  • Comments

Integer

Used for whole numbers.

quantity = fields.Integer(    string='Quantity')

Float

Used for decimal values.

amount = fields.Float(    string='Amount')

Boolean

Used for true/false values.

is_approved = fields.Boolean(    string='Approved')

Selection

Used when users need to select from predefined options.

state = fields.Selection(    [        ('draft', 'Draft'),        ('approved', 'Approved'),        ('rejected', 'Rejected'),    ],    default='draft')

Relational Fields

Relationships are particularly important in Odoo because ERP processes involve many connected business objects.

Many2one

A record links to one record from another model.

customer_id = fields.Many2one(    'res.partner',    string='Customer')

A credit approval can therefore be linked to one customer.

One2many

One record can contain multiple related records.

For example:

line_ids = fields.One2many(    'credit.approval.line',    'approval_id',    string='Approval Lines')

This could represent multiple approval conditions associated with one approval request.

Many2many

Multiple records can be linked on both sides.

For example:

user_ids = fields.Many2many(    'res.users',    string='Approvers')

This allows multiple users to be assigned.

2. Understanding Odoo Views

A model defines the data and logic, but users need an interface to interact with that data.

This is where views come in.

Odoo views determine how records are displayed and edited.

Common view types include:

  • Form
  • List
  • Kanban
  • Search
  • Calendar
  • Pivot
  • Graph
  • Activity

Form Views

A form view allows users to create and edit individual records.

Example:

<record id="view_credit_approval_form"
        model="ir.ui.view">

    <field name="name">
        credit.approval.form
    </field>

    <field name="model">
        credit.approval
    </field>

    <field name="arch"
           type="xml">

        <form>
            <sheet>

                <group>
                    <field name="name"/>
                    <field name="customer_id"/>
                    <field name="amount"/>
                    <field name="state"/>
                </group>

            </sheet>
        </form>

    </field>

</record>

The model determines what data exists.

The view determines how users see and interact with that data.

List Views

List views display multiple records.

For example:

<list>
    <field name="name"/>
    <field name="customer_id"/>
    <field name="amount"/>
    <field name="state"/>
</list>

A user could see:

ReferenceCustomerCredit LimitStatus
CA001ABC Ltd₹50,000Draft
CA002XYZ Pvt Ltd₹100,000Approved
CA003Global Traders₹75,000Rejected

List views are particularly useful for:

  • Sales orders
  • Purchase orders
  • Customers
  • Inventory records
  • Approval requests
  • Tasks

Kanban Views

Kanban views display records as cards.

For example:

┌──────────────┐
│ Draft        │
│              │
│ CA001        │
│ ABC Ltd      │
└──────────────┘

┌──────────────┐
│ Approved     │
│              │
│ CA002        │
│ XYZ Pvt Ltd  │
└──────────────┘

Kanban views are useful for workflows where records move between stages.

Examples include:

  • CRM opportunities
  • Projects
  • Helpdesk tickets
  • Approval workflows

Search Views

Search views help users find and filter records.

For example:

<search>
    <field name="name"/>
    <field name="customer_id"/>
    <field name="state"/>
</search>

You can also create filters for common business requirements.

For example:

My Approvals
Approved
Pending Approval
Rejected
High Credit Limit

This makes large datasets easier to manage.

3. Actions and Menus

A model and view alone are not enough.

Users need a way to access the functionality.

An Odoo module commonly uses:

Menu → Action → View → Model

For example:

Sales
   ↓
Credit Approvals
   ↓
Credit Approval List
   ↓
Credit Approval Form

An action can connect the menu with the appropriate model and views.

Example:

<record id="action_credit_approval"
        model="ir.actions.act_window">

    <field name="name">
        Credit Approvals
    </field>

    <field name="res_model">
        credit.approval
    </field>

    <field name="view_mode">
        list,form
    </field>

</record>

4. Understanding Odoo Security

Security is one of the most important parts of module development.

A module should not only determine what users can see but also what they are allowed to do.

Odoo security generally involves several mechanisms:

  • User groups
  • Access Control Lists (ACLs)
  • Record rules
  • Field-level restrictions

These mechanisms operate at different levels.

Access Control Lists

Access Control Lists determine whether a user has permission to perform operations on a model.

The four main operations are:

PermissionMeaning
ReadView records
CreateCreate records
WriteModify records
DeleteDelete records

A typical ACL file is:

security/ir.model.access.csv

Example:

id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_credit_user,credit.approval.user,model_credit_approval,base.group_user,1,1,1,0

This could allow a user to:

  • Read
  • Create
  • Modify

but not delete credit approval records.

Why ACLs Are Important

Imagine a company has two roles:

Sales User

Can:

  • Create approval requests
  • View their requests
  • Modify draft requests

Cannot:

  • Approve requests
  • Delete approved requests

Sales Manager

Can:

  • View requests
  • Approve requests
  • Reject requests
  • Modify records

These permissions can be implemented using appropriate groups and access rights.

5. Understanding Record Rules

ACLs answer:

Can this user perform an operation on this model?

Record rules answer:

Which records can this user access?

This distinction is extremely important.

For example, suppose there are 1,000 credit approval records.

A salesperson may be allowed to read the credit.approval model but should only see their own requests.

A record rule can restrict access to records associated with the current user.

Conceptually:

Credit Approval Records
        │
        ├── User A → Own Records
        ├── User B → Own Records
        └── Manager → All Records

This provides much more granular security.

ACL vs Record Rules

A simple way to remember the difference:

ACL

What can the user do?

Record Rule

Which records can the user do it to?

For example:

ACL:

Salesperson can read credit approvals.

Record Rule:

Salesperson can only read credit approvals where they are the assigned salesperson.

Both mechanisms may work together.

6. User Groups

Security rules are often assigned to user groups.

For example:

Credit Approval User
Credit Approval Manager
Credit Approval Administrator

You can then configure different permissions for each group.

Example:

RoleReadCreateWriteDeleteApprove
User✓✓✓✗✗
Manager✓✓✓✗✓
Administrator✓✓✓✓✓

This provides a structured security hierarchy.

7. Combining Models, Views and Security

Now let's see how the three components work together.

Suppose a company wants a Purchase Approval Module.

Model

purchase.approval

It contains:

  • Purchase Order
  • Requester
  • Amount
  • Approver
  • Status
  • Approval Date

View

The form provides:

Purchase Order
Requester
Amount
Approver
Status

[Submit]
[Approve]
[Reject]

Security

Purchase Users:

Create
Read
Write

Purchase Managers:

Create
Read
Write
Approve
Reject

The result is a complete business application.

8. Using Inheritance in Odoo

One of the biggest advantages of Odoo development is that existing functionality can be extended through inheritance.

Suppose you want to add a field to the standard Sales Order model.

You can use:

from odoo import models, fieldsclass SaleOrder(models.Model):    _inherit = 'sale.order'    customer_reference = fields.Char(        string='Customer Reference'    )

This extends the existing model instead of modifying Odoo's core source code.

View Inheritance

Views can also be inherited.

For example, a custom module could add a field to an existing Sales Order form.

Conceptually:

<record id="sale_order_form_inherit"
        model="ir.ui.view">

    <field name="model">
        sale.order
    </field>

    <field name="inherit_id"
           ref="sale.view_order_form"/>

    <field name="arch"
           type="xml">

        <xpath expr="//field[@name='partner_id']"
               position="after">

            <field name="customer_reference"/>

        </xpath>

    </field>

</record>

This allows developers to extend standard Odoo interfaces without replacing the complete original view.

9. Business Logic Belongs in the Model

Views should primarily control the presentation and interaction of data.

Business logic should generally remain in Python models.

For example:

from odoo.exceptions import UserErrordef action_approve(self):    for record in self:        if not record.approver_id:            raise UserError(                'An approver must be assigned.'            )        record.state = 'approved'

The approval logic is therefore reusable from the user interface and other parts of the system.

10. Computed Fields

Odoo models can also contain calculated fields.

For example:

total_amount = fields.Float(    compute='_compute_total_amount',    store=True)

The calculation can then be implemented in Python.

Computed fields are useful for:

  • Totals
  • Margins
  • Status calculations
  • KPIs
  • Derived values

Developers should carefully consider whether a computed field should be stored, especially when working with large datasets.

11. Constraints and Data Validation

Models can also enforce business rules.

For example, a company may not allow a negative credit limit.

A validation rule can prevent invalid data from being saved.

Conceptually:

Credit Limit < 0
       ↓
Validation Error
       ↓
Record Not Saved

This protects data quality at the model level instead of relying only on the user interface.

12. Security Should Not Depend on the View

A common mistake is assuming that hiding a button or field makes something secure.

For example:

<field name="credit_limit"
       invisible="1"/>

This only affects the interface.

It does not automatically provide complete access control.

Security should be implemented using appropriate:

  • Groups
  • ACLs
  • Record rules
  • Field restrictions

A user should not be able to access restricted information simply because a button or field is hidden from the screen.

13. Be Careful With sudo()

Developers sometimes use:

self.env['credit.approval'].sudo()

to bypass access restrictions.

While sudo() has legitimate uses, it should not be used simply to make permission errors disappear.

Before using it, developers should ask:

Does this operation genuinely need elevated privileges?

If not, the correct solution may be to configure the appropriate security groups or record rules.

14. Recommended Module Structure

A typical module might look like:

credit_approval/
│
├── __init__.py
├── __manifest__.py
│
├── models/
│   ├── __init__.py
│   └── credit_approval.py
│
├── views/
│   ├── credit_approval_views.xml
│   └── menu.xml
│
├── security/
│   ├── ir.model.access.csv
│   └── security.xml
│
├── data/
│   └── data.xml
│
├── wizard/
│   ├── __init__.py
│   └── approval_wizard.py
│
└── tests/
    ├── __init__.py
    └── test_credit_approval.py

Not every module requires every directory, but keeping a predictable structure makes development and maintenance easier.

15. The Role of __manifest__.py

Every module needs a manifest describing the module and its dependencies.

Example:

{    'name': 'Customer Credit Approval',    'version': '1.0',    'depends': [        'sale',    ],    'category': 'Sales',    'data': [        'security/security.xml',        'security/ir.model.access.csv',        'views/credit_approval_views.xml',        'views/menu.xml',    ],    'installable': True,}

The order of data files can matter.

For example, security definitions should be available before records that depend on them.

Developers should also keep dependencies limited to the modules actually required.

16. Testing Models, Views and Security

A custom module should be tested from three perspectives.

Model Testing

Check:

  • Record creation
  • Field calculations
  • Constraints
  • Business logic
  • Workflow transitions

View Testing

Check:

  • Forms
  • Lists
  • Search
  • Buttons
  • Menus
  • User experience

Security Testing

Test different users:

Sales User
Sales Manager
Administrator

Make sure each role can perform exactly the operations it is supposed to perform.

17. Common Development Mistakes

Modifying Odoo Core

Direct core modifications can make upgrades and maintenance more difficult.

Better: Use custom modules and inheritance.

Ignoring Record Rules

ACLs alone may not provide the required record-level restrictions.

Better: Combine ACLs and record rules when necessary.

Using sudo() Everywhere

This can bypass security unexpectedly.

Better: Use elevated access only when justified.

Putting Business Logic in Views

Complex logic becomes harder to maintain.

Better: Keep business logic in Python models.

Creating Huge Modules

Putting unrelated functionality into one module creates unnecessary dependencies.

Better: Keep modules focused and modular.

Testing Only as Administrator

Administrator access can hide security problems.

Better: Test with realistic user roles.

Hard-Coding Business Rules

Business rules often change.

Better: Make appropriate business parameters configurable.

Models + Views + Security: The Complete Picture

The relationship can be summarized as:

                 ODOO MODULE
                     │
        ┌────────────┼────────────┐
        │            │            │
        ▼            ▼            ▼
     MODELS        VIEWS       SECURITY
        │            │            │
     Data &        User        Access &
     Logic       Interface     Rules
        │            │            │
        └────────────┼────────────┘
                     ▼
             Business Workflow
                     │
                     ▼
              Business Users

A successful Odoo module needs all three layers to work together.

Best Practices Checklist

Before deploying a custom Odoo module, check:

  • Requirement is clearly documented
  • Standard Odoo functionality has been evaluated
  • Models are logically designed
  • Field relationships are appropriate
  • Business logic is implemented in Python
  • Views are clean and maintainable
  • Model inheritance is used where appropriate
  • View inheritance is used where appropriate
  • ACLs are configured
  • Record rules are reviewed
  • User groups are correctly defined
  • Sensitive fields are properly protected
  • sudo() is used only when necessary
  • Automated tests are included
  • Different user roles have been tested
  • Dependencies are minimized
  • Module documentation is available
  • Git version control is used
  • Changes are tested in staging before production

How ERP Harbor Can Help With Odoo Module Development

Custom Odoo development requires more than adding fields and buttons. The solution should fit the business process while remaining secure, maintainable, and upgrade-friendly.

ERP Harbor Consulting Services provides Odoo development services including:

  • Custom Odoo module development
  • Python development
  • Odoo model customization
  • XML view development
  • Security and access-rule configuration
  • Workflow development
  • Manufacturing customization
  • Inventory customization
  • Sales and Purchase customization
  • Accounting customization
  • API and third-party integrations
  • Custom reports and dashboards
  • Odoo migration and upgrades
  • Testing and debugging
  • Odoo support and maintenance

Our approach is to first understand the business requirement, evaluate standard Odoo functionality, and then develop custom functionality where it provides genuine value.

Conclusion

Models, Views, and Security Rules form the foundation of Odoo module development.

Models define the business data and logic. Views provide the interface through which users interact with that data. Security rules ensure that users can access only the records and operations appropriate to their roles.

When these three components are designed together, developers can create Odoo modules that are:

  • Secure
  • Scalable
  • Maintainable
  • User-friendly
  • Upgrade-friendly
  • Business-focused

Whether you're building a small approval workflow or a complete industry-specific Odoo application, understanding the relationship between models, views, and security is essential for creating reliable ERP customizations.

Odoo Development Environment: Best Practices for Building Custom Modules