Development Book V18: Data fields

Data fields

In Odoo, a model serves as a blueprint that defines the structure and behavior of data entities. Essentially, each model represents a database table, and its attributes (called fields) correspond to the table's columns. A model class contains field definitions and the logic to manage the data.

To begin creating a custom model, we place the Python file in the appropriate directory, such as:

models > university_student.py

1. Below is a custom model designed to manage student data within a university student management system


# -*- coding: utf-8 -*-
from datetime import date
from odoo import models, fields, api
from dateutil.relativedelta import relativedelta

class UniversityStudent(models.Model):
    """Model to store student information."""
    _name = "university.student"
    _description = "University Student Records"
    _inherit = ['mail.thread', 'mail.activity.mixin']

    # This is the sequential ID shown at the top of the form
    student_id = fields.Char(
        string='Student ID', required=True, copy=False, readonly=True,
        default=lambda self: 'New'
    )
    # This links to a res.partner record for the student's name and contact info
    student_name = fields.Many2one('res.partner', string="Student Name", required=True)

    # Personal Information
    birth_date = fields.Date(string='Date of Birth')
    student_age = fields.Integer(string='Age', compute='_compute_student_age', store=True)
    gender_type = fields.Selection([
        ('male', 'Male'),
        ('female', 'Female'),
        ('other', 'Other')
    ], string='Gender')
    blood_type = fields.Selection([
        ('A+', 'A+'), ('A-', 'A-'),
        ('B+', 'B+'), ('B-', 'B-'),
        ('AB+', 'AB+'), ('AB-', 'AB-'),
        ('O+', 'O+'), ('O-', 'O-')
    ], string='Blood Type')

    # Contact & Family
    country_id = fields.Many2one('res.country', string='Country')
    father_name = fields.Char(string="Father's Name")
    mother_name = fields.Char(string="Mother's Name")
    mobile_phone = fields.Char(string='Mobile Phone', related='student_name.mobile', readonly=False)
    landline = fields.Char(string='Landline', related='student_name.phone', readonly=False)

    # Academic History One2many relationship
    enrollment_history = fields.One2many(
        'university.enrollment.history',
        'student_id',
        string='Enrollment History'
    )

    @api.depends('birth_date')
    def _compute_student_age(self):
        """Calculate age from birth date."""
        for record in self:
            if record.birth_date:
                today = date.today()
                birth = record.birth_date
                record.student_age = today.year - birth.year - (
                    (today.month, today.day) < (birth.month, birth.day))
            else:
                record.student_age = 0

class UniversityEnrollmentHistory(models.Model):
    """Stores the academic history for a student."""
    _name = "university.enrollment.history"
    _description = "Student Enrollment History"

    student_id = fields.Many2one('university.student', string='Student Reference')
    course_level = fields.Char(string='Course Level', required=True)
    department = fields.Char(string='Department', required=True)
    academic_session = fields.Char(string='Academic Session', required=True)

Fields in a model class, declared as attributes, determine the specific kind of data the model will handle and contribute to its overall data structure. The range of non-relational field types offered is presented below

Char: Stores single-line text values (names, codes, titles).

Text: Handles multi-line text content (descriptions, notes).

Selection: Creates dropdown lists with predefined options.

Binary: Manages file storage and binary data (images, documents).

Html: Stores HTML-formatted rich text content.

Boolean: Handles True/False values for flags and toggles.

Date: Stores date values only (YYYY-MM-DD format).

Datetime: Stores combined date and time values (YYYY-MM-DD HH:MM:SS format).

Date Field Utilities

  • fields.Date.to_date(string) - Converts string to date object
  • fields.Date.to_string(date) - Converts date object to string
  • fields.Date.today() - Returns current date
  • fields.Date.context_today(record, timestamp) - Returns context-aware date

Datetime Field Utilities

  • fields.Datetime.to_datetime(string) - Converts string to datetime object
  • fields.Datetime.to_string(datetime) - Converts datetime object to string
  • fields.Datetime.now() - Returns current datetime
  • fields.Datetime.context_timestamp(record, timestamp) - Adjusts datetime to user's timezone

Float: Stores decimal numbers and floating-point values.

Monetary: Handles currency amounts with proper formatting and conversion.

Many2one: Links current model to a single record in another model (many-to-one relationship).

One2many: Creates inverse Many2one relationships, linking one record to multiple related records.

Many2many: Establishes bidirectional many-to-many relationships between models.

2. With the new fields now part of our model structure, the following phase requires setting up the form view to showcase these fields in the interface. The code example provided illustrates how to render these fields for user interaction.


<?xml version="1.0" encoding="utf-8"?>
<odoo>
   <record id="university_student_form_view" model="ir.ui.view">
       <field name="name">university.student.form</field>
       <field name="model">university.student</field>
       <field name="arch" type="xml">
           <form>
               <sheet>
                   <div class="oe_title">
                       <h1>
                           <field name="student_id" readonly="1"/>
                       </h1>
                   </div> 
                   <group>
                       <group string="Personal Information">
                           <field name="student_name"
                                  widget="res_partner_many2one"
                                  context="{'res_partner_search_mode': 'customer'}"
                                  options='{"always_reload": True}'/>
                           <field name="birth_date"/>
                           <field name="student_age"/>
                           <field name="gender_type"/>
                           <field name="blood_type"/>
                       </group>
                       <group string="Contact & Family">
                           <field name="country_id"/>
                           <field name="father_name"/>
                           <field name="mother_name"/>
                           <field name="mobile_phone"/>
                           <field name="landline"/>
                       </group>
                   </group>
                   <notebook>
                       <page string="Academic History">
                           <field name="enrollment_history">
                               <list editable="bottom">
                                   <field name="course_level" required="1"/>
                                   <field name="department" required="1"/>
                                   <field name="academic_session" required="1"/>
                               </list>
                           </field>
                       </page>
                   </notebook>
               </sheet>
           </form>
       </field>
   </record>

   <!-- Tree View -->
   <record id="university_student_tree_view" model="ir.ui.view">
       <field name="name">university.student.list</field>
       <field name="model">university.student</field>
       <field name="arch" type="xml">
           <list>
               <field name="student_id"/>
               <field name="student_name"/>
               <field name="student_age"/>
               <field name="gender_type"/>
               <field name="country_id"/>
           </list>
       </field>
   </record>

   <!-- Action -->
   <record id="university_student_action" model="ir.actions.act_window">
       <field name="name">University Students</field>
       <field name="res_model">university.student</field>
       <field name="view_mode">list,form</field>
   </record>
   <menuitem id="menu_university" name="University" sequence="1"/>

   <!-- Menu -->
   <menuitem id="university_student_menu"
             name="Students"
             parent="menu_university"
             action="university_student_action"/>
</odoo>

3. Following the module upgrade process, the modified form view appears in the user interface.

odoo-development
whatsapp_icon
location

Calicut

Cybrosys Technologies Pvt. Ltd.
Neospace, Kinfra Techno Park
Kakkancherry, Calicut
Kerala, India - 673635

location

Kochi

Cybrosys Technologies Pvt. Ltd.
1st Floor, Thapasya Building,
Infopark, Kakkanad,
Kochi, India - 682030.

location

Bangalore

Cybrosys Techno Solutions
The Estate, 8th Floor,
Dickenson Road,
Bangalore, India - 560042

Send Us A Message