Chapter 12: Inheritance

Az Odoo egyik erőteljes aspektusa a modularitása. Egy modul egy üzleti igényre van szánva, de a modulok egymással is kölcsönhatásba léphetnek. Ez hasznos egy meglévő modul funkcionalitásának bővítésére. Például az ingatlanforgatókönyvünkben azt szeretnénk, hogy az értékesítő ingatlanjainak listája közvetlenül megjelenjen a szokásos felhasználói nézetben.

De mielőtt rátérnénk az Odoo modul öröklődésének részleteire, nézzük meg, hogyan módosíthatjuk a szabványos CRUD (Create, Retrieve, Update vagy Delete) metódusok viselkedését.

Python öröklődés

Megjegyzés

Cél: ennek a szakasznak a végén:

  • It should not be possible to delete a property which is not new or cancelled.

Törlés
  • Amikor egy ajánlat létrejön, az ingatlan állapotának «Ajánlat érkezett» állapotra kell változnia.

  • Nem szabad lehetővé tenni egy olyan ajánlat létrehozását, amely alacsonyabb áron van, mint egy meglévő ajánlat.

Létrehozás

Az ingatlan modulunkban soha nem kellett semmi specifikusat fejlesztenünk ahhoz, hogy végrehajthassuk a szokásos CRUD műveleteket. Az Odoo keretrendszer biztosítja a szükséges eszközöket ezek végrehajtásához. Valójában az ilyen műveletek már szerepelnek a modellünkben a klasszikus Python öröklésnek köszönhetően:

from odoo import fields, models

class TestModel(models.Model):
    _name = "test_model"
    _description = "Test Model"

    ...

A class TestModel osztályunk örökli a Model osztályt, amely biztosítja a create(), read(), write() és unlink() metódusokat.

Ezek a metódusok (és bármely más, a Model osztályon definiált metódus) kiterjeszthetők specifikus üzleti logika hozzáadására:

from odoo import fields, models

class TestModel(models.Model):
    _name = "test_model"
    _description = "Test Model"

    ...

    @api.model
    def create(self, vals):
        # Do some business logic, modify vals...
        ...
        # Then call super to execute the parent method
        return super().create(vals)

A model() dekorátor szükséges a create() metódushoz, mert a rekordhalmaz self tartalma nem releváns a létrehozás kontextusában, de nem szükséges a többi CRUD metódushoz.

Fontos megjegyezni, hogy bár közvetlenül felülírhatjuk a unlink() metódust, szinte mindig érdemesebb egy új metódust írni a ondelete() dekorátorral. Az ezzel a dekorátorral jelölt metódusok a unlink() során kerülnek meghívásra, és elkerülik azokat a problémákat, amelyek a modell moduljának eltávolítása során jelentkezhetnek, amikor a unlink() közvetlenül felül van írva.

Python 3-ban a super() egyenértékű a super(TestModel, self) kifejezéssel. Az utóbbi szükséges lehet, amikor a szülő metódust egy módosított rekordhalmazzal kell meghívni.

Veszély

  • Nagyon fontos, hogy mindig hívjuk meg a super()-t, hogy elkerüljük a folyamat megszakítását. Csak néhány nagyon specifikus eset van, amikor nem akarjuk meghívni.

  • Győződjön meg róla, hogy mindig a szülő metódussal konzisztens adatokat ad vissza. Például, ha a szülő metódus egy dict()-et ad vissza, akkor a felülírásnak is egy dict()-et kell visszaadnia.

Exercise

Adjon hozzá üzleti logikát a CRUD metódusokhoz.

  • Prevent deletion of a property if its state is not «New» or «Cancelled»

Tipp: hozzon létre egy új metódust a ondelete() dekorátorral, és ne feledje, hogy a self több rekordot tartalmazó rekordhalmaz is lehet.

  • Ajánlat létrehozásakor állítsa az ingatlan állapotát «Ajánlat érkezett» értékre. Hibát kell jelezni, ha a felhasználó alacsonyabb összegű ajánlatot próbál létrehozni, mint egy meglévő ajánlat.

Tipp: a property_id mező elérhető a vals-ban, de ez egy int. Egy estate.property objektum példányosításához használja a self.env[model_name].browse(value) (példa)

Modell öröklés

Referencia: a témával kapcsolatos dokumentáció megtalálható a Öröklés és kiterjesztés.

Az ingatlan modulunkban szeretnénk megjeleníteni az értékesítőhöz kapcsolódó ingatlanok listáját közvetlenül a Beállítások / Felhasználók és Cégek / Felhasználók űrlap nézetben. Ehhez hozzá kell adnunk egy mezőt a res.users modellhez, és módosítanunk kell a nézetét, hogy megjelenítse azt.

Az Odoo két öröklési mechanizmust biztosít, hogy moduláris módon bővítsen egy meglévő modellt.

Az első öröklési mechanizmus lehetővé teszi a modulok számára, hogy módosítsák egy másik modulban definiált modell viselkedését az alábbi módokon:

  • mezők hozzáadása a modellhez,

  • mezők definíciójának felülírása a modellben,

  • korlátozások hozzáadása a modellhez,

  • módszerek hozzáadása a modellhez,

  • létező módszerek felülírása a modellben.

A második öröklési mechanizmus (delegálás) lehetővé teszi, hogy egy modell minden rekordja kapcsolódjon egy szülő modell rekordjához, és átlátható hozzáférést biztosítson a szülő rekord mezőihez.

Öröklési módszerek

Az Odoo-ban az első mechanizmus messze a leggyakrabban használt. Esetünkben egy mezőt szeretnénk hozzáadni egy meglévő modellhez, ami azt jelenti, hogy az első mechanizmust fogjuk használni. Például:

from odoo import fields, models

class InheritedModel(models.Model):
    _inherit = "inherited.model"

    new_field = fields.Char(string="New Field")

Egy gyakorlati példa, ahol két mezőt adnak hozzá egy modellhez, itt található.

Konvenció szerint minden örökölt modellt a saját Python fájljában definiálnak. Példánkban ez a models/inherited_model.py lenne.

Exercise

Adjon hozzá egy mezőt a Felhasználókhoz.

  • Adja hozzá a következő mezőt a res.users-hez:

Mező

Típus

property_ids

One2many mező inverze, amely az értékesítőt hivatkozza az estate.property-ben

  • Adjon hozzá egy domaint a mezőhöz, hogy csak az elérhető ingatlanokat listázza.

A következő részben adjuk hozzá a mezőt a nézethez, és ellenőrizzük, hogy minden jól működik-e!

Nézet öröklés

Referencia: a témával kapcsolatos dokumentáció megtalálható a Öröklés hivatkozás alatt.

Megjegyzés

Cél: ennek a résznek a végére az értékesítőhöz kapcsolódó elérhető ingatlanok listájának meg kell jelennie a felhasználói űrlap nézetükben

Felhasználók

A meglévő nézetek helyben történő módosítása helyett (felülírással), az Odoo nézet öröklést biztosít, ahol a gyermek «kiterjesztés» nézetek a gyökér nézetek tetejére kerülnek alkalmazásra. Ezek a kiterjesztések tartalmat adhatnak hozzá vagy távolíthatnak el a szülő nézetükből.

Egy kiterjesztés nézet a szülőjére az inherit_id mező használatával hivatkozik. Egyetlen nézet helyett az arch mezője számos xpath elemet tartalmaz, amelyek kiválasztják és módosítják a szülő nézetük tartalmát:

<record id="inherited_model_view_form" model="ir.ui.view">
    <field name="name">inherited.model.form.inherit.test</field>
    <field name="model">inherited.model</field>
    <field name="inherit_id" ref="inherited.inherited_model_view_form"/>
    <field name="arch" type="xml">
        <!-- find field description and add the field
             new_field after it -->
        <xpath expr="//field[@name='description']" position="after">
          <field name="new_field"/>
        </xpath>
    </field>
</record>
expr

Egy XPath kifejezés, amely egyetlen elemet választ ki a szülő nézetben. Hibát jelez, ha nem talál elemet vagy egynél több elemet talál

position

Művelet, amelyet az egyező elemre kell alkalmazni:

inside

hozzáfűzi az xpath törzsét a megfelelő elem végéhez

replace

az egyező elemet az xpath törzsével helyettesíti, az új törzs bármely $0 csomópont előfordulását az eredeti elemmel helyettesítve

before

az xpath törzsét testvérként beszúrja az egyező elem elé

after

az xpaths törzsét testvérként beszúrja az egyező elem után

attributes

módosítja a megfelelő elem attribútumait az xpath törzsében található speciális attribute elemek segítségével

Egyetlen elem egyezésekor a position attribútum közvetlenül a megtalálandó elemre állítható. Az alábbi két öröklés ugyanazt az eredményt adja.

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

<field name="description" position="after">
    <field name="idea_ids" />
</field>

A nézet öröklésének kiterjesztésére egy példa található itt.

Exercise

Adjon hozzá mezőket a Felhasználók nézethez.

Adja hozzá a property_ids mezőt a base.view_users_form-hoz egy új jegyzetfüzet oldalon.

Tipp: a felhasználók nézetének öröklésére egy példa található itt.

Az öröklés széles körben használt az Odoo-ban a moduláris koncepció miatt. Ne habozzon elolvasni a megfelelő dokumentációt további információkért!

In the next chapter, we will learn how to interact with other modules.