How to Build Custom Odoo Modules: A Developer's Guide to OWL, ORM & Inheritance

Developer guide to building custom Odoo modules. Covers module structure, OWL framework, ORM inheritance, views, security rules, testing, and OCA guidelines.

E

ECOSIRE Research and Development Team

ECOSIRE टीम

19 फ़रवरी 20267 मिनट पढ़ें1.4k शब्द

कस्टम ओडू मॉड्यूल कैसे बनाएं: ओडब्लूएल, ओआरएम और इनहेरिटेंस के लिए एक डेवलपर की मार्गदर्शिका

जब ओडू के 82 आधिकारिक मॉड्यूल और 40,000+ सामुदायिक मॉड्यूल आपकी सटीक व्यावसायिक आवश्यकताओं को पूरा नहीं करते हैं, तो कस्टम मॉड्यूल विकास इस अंतर को भर देता है। यह मार्गदर्शिका 2026 में ओडू मॉड्यूल के निर्माण के बुनियादी सिद्धांतों को शामिल करती है, जिसमें मॉड्यूल संरचना, ओडब्लूएल फ्रंटएंड फ्रेमवर्क, ओआरएम पैटर्न, इनहेरिटेंस तंत्र और ओसीए (ओडू कम्युनिटी एसोसिएशन) दिशानिर्देशों के साथ संरेखित सर्वोत्तम अभ्यास शामिल हैं।

कस्टम ओडू मॉड्यूल क्या है?

एक कस्टम ओडू मॉड्यूल पायथन बैकएंड लॉजिक, एक्सएमएल व्यू परिभाषाओं, जावास्क्रिप्ट फ्रंटएंड घटकों और सुरक्षा नियमों का एक स्व-निहित पैकेज है जो ओडू की कार्यक्षमता को बढ़ाता है। मॉड्यूल पूरी तरह से नई सुविधाएँ जोड़ सकते हैं, मौजूदा व्यवहार को संशोधित कर सकते हैं, या ओडू को बाहरी सिस्टम के साथ एकीकृत कर सकते हैं। ओडू का प्रत्येक टुकड़ा अपने आप में एक मॉड्यूल है, जो वास्तुकला को स्वाभाविक रूप से विस्तार योग्य बनाता है।

मॉड्यूल निर्देशिका संरचना

एक सुव्यवस्थित मॉड्यूल इस मानक संरचना का अनुसरण करता है:

my_custom_module/
├── __init__.py              # Python package init
├── __manifest__.py          # Module metadata and dependencies
├── models/
│   ├── __init__.py
│   └── my_model.py          # Business logic and data models
├── views/
│   ├── my_model_views.xml   # Form, tree, and kanban views
│   └── menu.xml             # Menu items and actions
├── security/
│   ├── ir.model.access.csv  # Access control list
│   └── security.xml         # Record rules and groups
├── data/
│   └── data.xml             # Default data records
├── static/
│   └── src/
│       ├── js/              # OWL components
│       ├── css/             # Stylesheets
│       └── xml/             # QWeb templates
├── wizard/                  # Transient models for wizards
├── reports/                 # QWeb report templates
└── tests/                   # Unit tests

प्रकट फ़ाइल

__manifest__.py फ़ाइल आपके मॉड्यूल की पहचान को परिभाषित करती है:

{
    'name': 'My Custom Module',
    'version': '18.0.1.0.0',
    'category': 'Custom',
    'summary': 'Short description of what the module does',
    'description': """
        Long description with details about
        features and configuration.
    """,
    'author': 'ECOSIRE',
    'website': 'https://ecosire.com',
    'license': 'LGPL-3',
    'depends': ['base', 'sale', 'stock'],
    'data': [
        'security/ir.model.access.csv',
        'views/my_model_views.xml',
        'views/menu.xml',
        'data/data.xml',
    ],
    'assets': {
        'web.assets_backend': [
            'my_custom_module/static/src/js/**/*',
            'my_custom_module/static/src/css/**/*',
            'my_custom_module/static/src/xml/**/*',
        ],
    },
    'installable': True,
    'application': False,
    'auto_install': False,
}

संस्करण परिपाटी: {odoo_version}.{major}.{minor}.{patch} (उदा., 18.0.1.0.0)।

ओआरएम के साथ काम करना

ओडू का ऑब्जेक्ट-रिलेशनल मैपिंग (ओआरएम) सभी बैकएंड विकास की नींव है। मॉडल डेटाबेस तालिकाओं पर मैप करते हैं, और ORM CRUD संचालन, गणना किए गए फ़ील्ड, बाधाएं और वर्कफ़्लो प्रबंधन प्रदान करता है।

एक मॉडल को परिभाषित करना

from odoo import models, fields, api

class ProjectTask(models.Model):
    _name = 'my_module.task'
    _description = 'Project Task'
    _order = 'priority desc, create_date desc'

    name = fields.Char(string='Task Name', required=True)
    description = fields.Html(string='Description')
    state = fields.Selection([
        ('draft', 'Draft'),
        ('in_progress', 'In Progress'),
        ('done', 'Done'),
        ('cancelled', 'Cancelled'),
    ], default='draft', tracking=True)
    assigned_to = fields.Many2one('res.users', string='Assigned To')
    deadline = fields.Date(string='Deadline')
    priority = fields.Selection([
        ('0', 'Normal'),
        ('1', 'Important'),
        ('2', 'Urgent'),
    ], default='0')
    tag_ids = fields.Many2many('my_module.tag', string='Tags')
    progress = fields.Float(compute='_compute_progress', store=True)

फ़ील्ड प्रकार संदर्भ

| फ़ील्ड प्रकार | पायथन प्रकार | केस का प्रयोग करें | |---|---|---| | चार | स्ट्र | संक्षिप्त पाठ (नाम, संदर्भ) | | पाठ | स्ट्र | लंबा सादा पाठ | | एचटीएमएल | स्ट्र | समृद्ध पाठ्य सामग्री | | पूर्णांक | int | पूर्णांक | | तैरना | तैरना | दशमलव संख्या | | बूलियन | बूल | सच्चे/झूठे झंडे | | दिनांक | दिनांक | बिना समय की तारीख | | दिनांकसमय | दिनांक समय | दिनांक समय सहित | | चयन | स्ट्र | ड्रॉपडाउन विकल्प | | अनेक2एक | int | एक रिकॉर्ड से लिंक करें | | एक2अनेक | सूची | Any2one का उल्टा | | अनेक2 अनेक | सूची | एकाधिक रिकॉर्ड से लिंक करें | | बाइनरी | बाइट्स | फ़ाइल संलग्नक |

परिकलित फ़ील्ड और बाधाएँ

@api.depends('subtask_ids.state')
def _compute_progress(self):
    for task in self:
        total = len(task.subtask_ids)
        done = len(task.subtask_ids.filtered(
            lambda t: t.state == 'done'
        ))
        task.progress = (done / total * 100) if total else 0

@api.constrains('deadline')
def _check_deadline(self):
    for task in self:
        if task.deadline and task.deadline < fields.Date.today():
            raise ValidationError(
                "Deadline cannot be in the past."
            )

वंशानुक्रम तंत्र

ओडू तीन प्रकार की विरासत प्रदान करता है, प्रत्येक का एक अलग उद्देश्य होता है:

1. वर्ग वंशानुक्रम (विस्तार)

फ़ील्ड या ओवरराइडिंग विधियों को जोड़कर मौजूदा मॉडल का विस्तार करें। यह सबसे आम पैटर्न है.

class SaleOrderExtend(models.Model):
    _inherit = 'sale.order'

    custom_reference = fields.Char(string='Custom Ref')
    approved_by = fields.Many2one('res.users')

    def action_confirm(self):
        # Add custom logic before standard confirmation
        for order in self:
            if order.amount_total > 10000 and not order.approved_by:
                raise UserError("Orders over $10,000 require approval.")
        return super().action_confirm()

2. प्रोटोटाइप वंशानुक्रम

एक नया मॉडल बनाएं जो मौजूदा मॉडल से सभी फ़ील्ड और विधियों की प्रतिलिपि बनाता है।

class CustomPartner(models.Model):
    _name = 'my_module.partner'
    _inherit = 'res.partner'   # Copies structure
    _description = 'Custom Partner'

3. प्रत्यायोजन विरासत

एक नया मॉडल बनाएं जो मौजूदा मॉडल को एक Any2one लिंक के माध्यम से सौंपता है। पैरेंट मॉडल के फ़ील्ड चाइल्ड मॉडल पर पारदर्शी रूप से दिखाई देते हैं।

class LibraryMember(models.Model):
    _name = 'library.member'
    _inherits = {'res.partner': 'partner_id'}

    partner_id = fields.Many2one('res.partner', required=True,
                                  ondelete='cascade')
    membership_date = fields.Date()
    member_number = fields.Char()

OWL फ्रेमवर्क (फ्रंटएंड)

Odoo 18 अपने फ्रंटएंड फ्रेमवर्क के रूप में OWL (Odoo वेब लाइब्रेरी) का उपयोग करता है। OWL रिएक्ट या Vue के समान एक घटक-आधारित ढांचा है लेकिन विशेष रूप से Odoo की जरूरतों के लिए डिज़ाइन किया गया है।

बुनियादी OWL घटक

/** @odoo-module */

import { Component, useState } from "@odoo/owl";
import { registry } from "@web/core/registry";

class TaskDashboard extends Component {
    static template = "my_module.TaskDashboard";

    setup() {
        this.state = useState({
            tasks: [],
            filter: 'all',
        });
        this.loadTasks();
    }

    async loadTasks() {
        this.state.tasks = await this.env.services.orm.searchRead(
            "my_module.task",
            [["state", "!=", "cancelled"]],
            ["name", "state", "assigned_to", "deadline"]
        );
    }

    get filteredTasks() {
        if (this.state.filter === 'all') return this.state.tasks;
        return this.state.tasks.filter(
            t => t.state === this.state.filter
        );
    }
}

क्यूवेब टेम्पलेट (एक्सएमएल)

<?xml version="1.0" encoding="UTF-8"?>
<templates xml:space="preserve">
    <t t-name="my_module.TaskDashboard">
        <div class="o_task_dashboard">
            <div class="task-filters">
                <button t-on-click="() => state.filter = 'all'">All</button>
                <button t-on-click="() => state.filter = 'in_progress'">
                    In Progress
                </button>
            </div>
            <div class="task-list">
                <t t-foreach="filteredTasks" t-as="task" t-key="task.id">
                    <div class="task-card">
                        <span t-esc="task.name"/>
                    </div>
                </t>
            </div>
        </div>
    </t>
</templates>

सुरक्षा विन्यास

प्रत्येक मॉडल को स्पष्ट पहुंच नियमों की आवश्यकता होती है। इनके बिना कोई भी उपयोगकर्ता मॉडल के डेटा तक नहीं पहुंच सकता.

प्रवेश नियंत्रण सूची (ir.model.access.csv)

id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_task_user,task.user,model_my_module_task,base.group_user,1,1,1,0
access_task_manager,task.manager,model_my_module_task,my_module.group_manager,1,1,1,1

रिकॉर्ड नियम (सुरक्षा.एक्सएमएल)

<record id="task_own_rule" model="ir.rule">
    <field name="name">Own Tasks Only</field>
    <field name="model_id" ref="model_my_module_task"/>
    <field name="domain_force">
        [('assigned_to', '=', user.id)]
    </field>
    <field name="groups" eval="[(4, ref('base.group_user'))]"/>
</record>

अपने मॉड्यूल का परीक्षण करना

Odoo, Odoo-विशिष्ट परीक्षण कक्षाओं के साथ unittest ढांचे का उपयोग करके पायथन इकाई परीक्षणों का समर्थन करता है:

from odoo.tests.common import TransactionCase

class TestTask(TransactionCase):
    def setUp(self):
        super().setUp()
        self.task = self.env['my_module.task'].create({
            'name': 'Test Task',
            'state': 'draft',
        })

    def test_task_creation(self):
        self.assertEqual(self.task.state, 'draft')
        self.assertEqual(self.task.progress, 0)

    def test_deadline_constraint(self):
        with self.assertRaises(ValidationError):
            self.task.write({
                'deadline': fields.Date.subtract(
                    fields.Date.today(), days=1
                ),
            })

इसके साथ परीक्षण चलाएँ: odoo-bin -d test_db --test-enable -i my_custom_module --stop-after-init

अक्सर पूछे जाने वाले प्रश्न

प्रश्न: कस्टम ओडू मॉड्यूल बनाने में कितना समय लगता है? सरल मॉड्यूल (नए फ़ील्ड, बुनियादी दृश्य) में 1-3 दिन लगते हैं। मध्यम मॉड्यूल (नए मॉडल, वर्कफ़्लो, रिपोर्ट) में 1-3 सप्ताह लगते हैं। जटिल मॉड्यूल (मल्टी-मॉडल सिस्टम, बाहरी एकीकरण, कस्टम OWL घटक) में 4-12 सप्ताह लगते हैं। उन व्यवसायों के लिए जिन्हें कस्टम मॉड्यूल की आवश्यकता है लेकिन इन-हाउस ओडू डेवलपर्स की कमी है, हमारी टीम से एक अनुभवी ओडू डेवलपर को नियुक्त करें

प्रश्न: क्या मुझे कोर ओडू कोड को संशोधित करना चाहिए या एक अलग मॉड्यूल बनाना चाहिए? हमेशा एक अलग मॉड्यूल बनाएं. कोर कोड को संशोधित करने से अपग्रेडेबिलिटी टूट जाती है और संस्करण अपडेट के दौरान मर्ज टकराव पैदा होता है। अपने कस्टम मॉड्यूल से मौजूदा मॉडल और दृश्यों का विस्तार करने के लिए इनहेरिटेंस का उपयोग करें।

प्रश्न: OCA दिशानिर्देश क्या हैं? ओडू कम्युनिटी एसोसिएशन (ओसीए) मॉड्यूल गुणवत्ता के लिए कोडिंग मानकों को प्रकाशित करता है, जिसमें नामकरण परंपराएं, दस्तावेज़ीकरण आवश्यकताएं, परीक्षण कवरेज अपेक्षाएं और कोड शैली नियम शामिल हैं। ओसीए दिशानिर्देशों का पालन यह सुनिश्चित करता है कि आपका मॉड्यूल रखरखाव योग्य है और व्यापक सामुदायिक पारिस्थितिकी तंत्र के साथ संगत है।

पेशेवर सहायता प्राप्त करना

कस्टम ओडू मॉड्यूल के निर्माण के लिए पायथन, जावास्क्रिप्ट, पोस्टग्रेएसक्यूएल और ओडू के फ्रेमवर्क सम्मेलनों में विशेषज्ञता की आवश्यकता होती है। चाहे आपको एक साधारण फ़ील्ड एक्सटेंशन या एक जटिल मल्टी-मॉड्यूल सिस्टम की आवश्यकता हो, ECOSIRE की Odoo अनुकूलन सेवाएँ OCA मानकों के अनुसार निर्मित उत्पादन-तैयार मॉड्यूल प्रदान करती हैं।

हमसे संपर्क करें अपनी कस्टम मॉड्यूल आवश्यकताओं पर चर्चा करने और विकास अनुमान प्राप्त करने के लिए।

शेयर करें:
E

लेखक

ECOSIRE Research and Development Team

ECOSIRE में एंटरप्राइज़-ग्रेड डिजिटल उत्पाद बना रहे हैं। Odoo एकीकरण, ई-कॉमर्स ऑटोमेशन, और AI-संचालित व्यावसायिक समाधानों पर अंतर्दृष्टि साझा कर रहे हैं।

WhatsApp पर चैट करें