11 - Creating Custom Models: models.Model
Welcome back! So far, we have set up our environment, mastered the command line, and learned how to structure a module. Now, it is time to write some actual Python code and build the foundation of our application: The Database Model.
In Odoo, you never have to write raw SQL CREATE TABLE statements. Instead, you write Python classes. Odoo’s incredibly powerful ORM (Object-Relational Mapping) reads your Python code and translates it into PostgreSQL database tables automatically.
Today, we are going to create our very first custom model.
1. The Anatomy of an Odoo Model
To create a new table in the database, your Python class must inherit from models.Model.
Let's imagine we are building a module to manage a Library. We need a database table to store all of our books. Here is what the absolute bare minimum Python file (library_book.py) looks like:
from odoo import models, fields
class LibraryBook(models.Model):
# _name is mandatory. It determines the database table name.
_name = 'library.book'
# _description is highly recommended for developer readability.
_description = 'Library Book Management'
What just happened? By simply defining _name = 'library.book', Odoo will go into PostgreSQL and create a brand new table called library_book (notice how the dot becomes an underscore!).
2. Adding Data Fields (Columns)
An empty table is useless. We need columns to store the book's title, the author, the price, and whether it is currently available. We do this by adding fields to our class.
Let's expand our LibraryBook model:
from odoo import models, fields
class LibraryBook(models.Model):
_name = 'library.book'
_description = 'Library Book Management'
# The 'name' field is a special reserved field in Odoo.
# It acts as the default display name for the record.
name = fields.Char(string='Book Title', required=True)
author = fields.Char(string='Author')
pages = fields.Integer(string='Number of Pages')
price = fields.Float(string='Price', digits=(10, 2))
is_available = fields.Boolean(string='Is Available?', default=True)
publish_date = fields.Date(string='Date Published')
Breaking Down the Fields:
fields.Char: A short text string. In the database, this becomes a VARCHAR.
string='...': This is the label that users will actually see on the computer screen.
required=True: This tells Odoo not to let the user save the record if this field is empty. It also adds a NOT NULL constraint in the database.
default=True: When a user clicks "New Book", this checkbox will already be checked for them.
3. The Magic of the ORM (Hidden Fields)
Here is a secret that surprises a lot of beginners: Odoo adds extra fields to your table behind your back.
Even though we only wrote 6 fields in our Python code, if you look at the PostgreSQL database, you will see 11 columns! Because we inherited from models.Model, Odoo automatically generated the following fields for system auditing:
id: A unique primary key for every book.
create_uid: The ID of the user who created the record.
create_date: The exact date and time the record was created.
write_uid: The ID of the last user to edit the record.
write_date: The exact date and time it was last edited.
You get all of this enterprise-level tracking for free, without writing a single line of code!
4. The Golden Security Rule
⚠️ Warning! If you write this Python code, install your module, and restart your server... you will not see your model anywhere in Odoo.
Why? Because Odoo is secure by default. If you create a new database table, nobody has permission to read or write to it, not even the system administrator!
Whenever you create a new models.Model, you must create an access rights rule in your security/ir.model.access.csv file.
Here is the code you need to add to that CSV file to give all internal users full access to your new Library Book model:
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_library_book_user,library.book.user,model_library_book,base.group_user,1,1,1,1
(Notice how model_library_book is just your _name with underscores instead of dots!)
5. Pro-Tips & Advice
💡 PRO TIP: The help Attribute If you want to create a fantastic user experience, use the help attribute on your fields. When a user hovers their mouse over the field label on the screen, a tooltip will appear explaining what the field does!
isbn_number = fields.Char(
string='ISBN',
help='Enter the 13-digit International Standard Book Number found on the back cover.'
)
- Naming Conventions: Always use lowercase letters and underscores for your field names (e.g., publish_date, not PublishDate). This is a strict Python (PEP8) and Odoo standard.
- The active Field: If you want the ability to "Archive" records instead of permanently deleting them, simply add active = fields.Boolean(default=True). Odoo will automatically add an "Archive" button to your form view!
There are no comments for now.