Modul készítése

Veszély

This tutorial is outdated. We recommend reading Server framework 101 instead.

Figyelem

This tutorial requires having installed Odoo

Az Odoo szerver indítása/leállítása

Az Odoo kliens/szerver architektúrát használ, amelyben a kliensek web böngészők, amelyek RPC-n keresztül érik el az Odoo szervert.

Az üzleti logika és a bővítések általában a szerver oldalon történnek, bár a kliens oldalon is hozzáadhatók támogató funkciók (pl. új adatmegjelenítés, mint az interaktív térképek).

A szerver indításához egyszerűen hívja meg a odoo-bin parancsot a shellben, szükség esetén hozzáadva a fájl teljes elérési útját:

odoo-bin

A szerver leállítása a terminálon kétszer megnyomott Ctrl-C billentyűkombinációval, vagy a megfelelő operációs rendszer folyamatának leállításával történik.

Odoo modul létrehozása

Mind a szerver, mind az ügyfél kiterjesztései modulokként vannak csomagolva, amelyek opcionálisan betöltődnek egy adatbázisba.

Az Odoo modulok vagy teljesen új üzleti logikát adhatnak hozzá egy Odoo rendszerhez, vagy módosíthatják és kiterjeszthetik a meglévő üzleti logikát: egy modul létrehozható, hogy hozzáadja az országának számviteli szabályait az Odoo általános számviteli támogatásához, míg a következő modul valós idejű vizualizációs támogatást ad egy buszflotta számára.

Így az Odoo-ban minden modulokkal kezdődik és végződik.

Egy modul összetétele

Egy Odoo modul számos elemet tartalmazhat:

Üzleti objektumok

Python osztályokként deklarálva, ezek az erőforrások automatikusan megmaradnak az Odoo által a konfigurációjuk alapján.

Objektum nézetek

Üzleti objektumok felhasználói felületének megjelenítése

Adatfájlok

XML vagy CSV fájlok, amelyek a modell metaadatait deklarálják:

Webes vezérlők

Kérések kezelése webböngészőkből

Statikus webadatok

A webes felület vagy weboldal által használt képek, CSS vagy javascript fájlok

Modulstruktúra

Minden modul egy könyvtár egy modul könyvtáron belül. A modul könyvtárakat a --addons-path opció használatával lehet megadni.

Javaslat

a legtöbb parancssori opció beállítható egy konfigurációs fájl használatával is

Egy Odoo modul a manifest által van deklarálva.

Egy modul egy Python csomag is, amely tartalmaz egy __init__.py fájlt, amely import utasításokat tartalmaz a modul különböző Python fájljaihoz.

Például, ha a modulnak van egyetlen mymodule.py fájlja, akkor a __init__.py tartalmazhatja:

from . import mymodule

Az Odoo biztosít egy mechanizmust egy új modul beállításához, a odoo-bin rendelkezik egy alparanccsal scaffold egy üres modul létrehozásához:

$ odoo-bin scaffold <module name> <where to put it>

A parancs létrehoz egy alkönyvtárat a modulod számára, és automatikusan létrehoz egy csomó szabványos fájlt egy modulhoz. A legtöbbjük egyszerűen megjegyzésként tartalmaz kódot vagy XML-t. Ezen fájlok többségének használatát a tutorial során fogjuk megmagyarázni.

Exercise

Modul létrehozása

Használja a fenti parancssort egy üres Open Academy modul létrehozásához, és telepítse az Odoo-ba.

Objektum-relációs leképezés

Az Odoo egyik kulcsfontosságú eleme az ORM réteg. Ez a réteg elkerüli, hogy a legtöbb SQL-t kézzel kelljen írni, és kiterjeszthetőségi és biztonsági szolgáltatásokat nyújt2.

Az üzleti objektumok Python osztályokként vannak deklarálva, amelyek kiterjesztik a Model-t, és integrálják őket az automatizált perzisztencia rendszerbe.

A modellek konfigurálhatók azáltal, hogy számos attribútumot állítanak be a definíciójuknál. A legfontosabb attribútum a _name, amely kötelező, és meghatározza a modell nevét az Odoo rendszerben. Íme egy minimálisan teljes modell definíció:

from odoo import models
class MinimalModel(models.Model):
    _name = 'test.model'

Modell mezők

A mezők arra szolgálnak, hogy meghatározzák, mit tárolhat a modell és hol. A mezők a modell osztály attribútumaiként vannak definiálva:

from odoo import models, fields

class LessMinimalModel(models.Model):
    _name = 'test.model2'

    name = fields.Char()

Gyakori attribútumok

Hasonlóan magához a modellhez, a mezői is konfigurálhatók, konfigurációs attribútumok paraméterként való átadásával:

name = fields.Char(required=True)

Néhány attribútum minden mezőnél elérhető, itt vannak a leggyakoribbak:

string (unicode, alapértelmezett: a mező neve)

A mező címkéje a felhasználói felületen (a felhasználók által látható).

required (bool, alapértelmezett: False)

Ha True, a mező nem lehet üres, vagy alapértelmezett értékkel kell rendelkeznie, vagy mindig értéket kell kapnia, amikor rekordot hoz létre.

help (unicode, alapértelmezett: '')

Hosszú formátum, segítségnyújtó eszköztippet biztosít a felhasználóknak a felhasználói felületen.

index (bool, alapértelmezett: False)

Kéri, hogy az Odoo hozzon létre egy adatbázis indexet az oszlopon.

Egyszerű mezők

There are two broad categories of fields: „simple” fields which are atomic values stored directly in the model’s table and „relational” fields linking records (of the same model or of different models).

Egyszerű mezők példái a következők: Boolean, Date, Char.

Fenntartott mezők

Az Odoo néhány mezőt létrehoz minden modellben1. Ezeket a mezőket a rendszer kezeli, és nem szabad írni rájuk. Olvashatók, ha hasznos vagy szükséges:

id (Id)

A rekord egyedi azonosítója a modelljében.

create_date (Datetime)

A rekord létrehozásának dátuma.

create_uid (Many2one)

A rekordot létrehozó felhasználó.

write_date (Datetime)

A rekord utolsó módosításának dátuma.

write_uid (Many2one)

a felhasználó, aki utoljára módosította a rekordot.

Speciális mezők

Alapértelmezés szerint az Odoo minden modellhez megkövetel egy name mezőt különböző megjelenítési és keresési viselkedésekhez. Az ezekre a célokra használt mező felülírható az _rec_name beállításával.

Exercise

Modell definiálása

Definiáljon egy új Course adatmodellt az openacademy modulban. Egy kurzusnak van címe és leírása. A kurzusoknak kötelezően kell, hogy legyen címük.

Adatfájlok

Az Odoo egy erősen adatvezérelt rendszer. Bár a viselkedés testreszabása Python kóddal történik, egy modul értékének része az adatokban rejlik, amelyeket betöltéskor állít be.

Javaslat

néhány modul kizárólag azért létezik, hogy adatokat adjon hozzá az Odoo-hoz

A modul adatai data files fájlokon keresztül vannak deklarálva, XML fájlok <record> elemekkel. Minden <record> elem létrehoz vagy frissít egy adatbázis rekordot.

<odoo>

        <record model="{model name}" id="{record identifier}">
            <field name="{a field name}">{a value}</field>
        </record>

</odoo>
  • A model az Odoo modell neve a rekordhoz.

  • Az id egy external identifier, amely lehetővé teszi a rekord hivatkozását (anélkül, hogy ismernénk az adatbázisban lévő azonosítóját).

  • A <field> elemeknek van egy name attribútuma, amely a mező neve a modellben (pl. description). A törzsük a mező értéke.

Az adatfájlokat a manifest fájlban kell deklarálni a betöltéshez, ezek deklarálhatók a 'data' listában (mindig betöltve) vagy a 'demo' listában (csak bemutató módban betöltve).

Exercise

Bemutató adatok meghatározása

Hozzon létre bemutató adatokat a Courses modell néhány bemutató kurzussal való feltöltésével.

Javaslat

Az adatfájlok tartalma csak akkor töltődik be, amikor egy modul telepítve vagy frissítve van.

Néhány módosítás után ne felejtse el használni a odoo-bin -u openacademy parancsot a változtatások adatbázisba mentéséhez.

Műveletek és menük

Az akciók és menük rendszeres rekordok az adatbázisban, amelyeket általában adatfájlokon keresztül deklarálnak. Az akciók háromféleképpen indíthatók el:

  1. menüpontokra kattintva (amelyek meghatározott akciókhoz kapcsolódnak)

  2. nézetekben lévő gombokra kattintva (ha ezek akciókhoz vannak kapcsolva)

  3. mint kontextuális akciók objektumokon

Mivel a menük deklarálása némileg összetett, létezik egy <menuitem> rövidítés, amely lehetővé teszi egy ir.ui.menu deklarálását és annak könnyebb összekapcsolását a megfelelő akcióval.

<record model="ir.actions.act_window" id="action_list_ideas">
    <field name="name">Ideas</field>
    <field name="res_model">idea.idea</field>
    <field name="view_mode">list,form</field>
</record>
<menuitem id="menu_ideas" parent="menu_root" name="Ideas" sequence="10"
          action="action_list_ideas"/>

Veszély

Az akciót az XML fájlban a hozzá tartozó menü előtt kell deklarálni.

Az adatfájlok sorrendben hajtódnak végre, az akció id-jének jelen kell lennie az adatbázisban, mielőtt a menü létrehozható.

Exercise

Új menübejegyzések meghatározása

Új menübejegyzések meghatározása a kurzusok eléréséhez az OpenAcademy menübejegyzés alatt. A felhasználónak képesnek kell lennie:

  • megjeleníteni az összes kurzus listáját

  • kurzusok létrehozása/módosítása

Alap nézetek

A nézetek határozzák meg, hogyan jelennek meg egy modell rekordjai. Minden nézettípus egy megjelenítési módot képvisel (rekordok listája, aggregációjuk grafikonja, …). A nézetek vagy típusuk alapján kérhetők le általánosan (pl. partnerek listája), vagy konkrétan azonosítójuk alapján. Általános kérések esetén a megfelelő típusú és legalacsonyabb prioritású nézet kerül felhasználásra (így minden típus legalacsonyabb prioritású nézete az alapértelmezett nézet az adott típushoz).

Nézet öröklés lehetővé teszi máshol deklarált nézetek módosítását (tartalom hozzáadása vagy eltávolítása).

Általános nézet deklaráció

Egy nézet az ir.ui.view modell rekordjaként van deklarálva. A nézet típusa az arch mező gyökéreleméből következik:

<record model="ir.ui.view" id="view_id">
    <field name="name">view.name</field>
    <field name="model">object_name</field>
    <field name="priority" eval="16"/>
    <field name="arch" type="xml">
        <!-- view content: <form>, <list>, <graph>, ... -->
    </field>
</record>

Veszély

A nézet tartalma XML.

The arch field must thus be declared as type="xml" to be parsed correctly.

list views

list views, also called list views, display records in a tabular form.

Their root element is <list>. The simplest form of the list view simply lists all the fields to display in the table (each field as a column):

<list string="Idea list">
    <field name="name"/>
    <field name="inventor_id"/>
</list>

Űrlap nézetek

Az űrlapokat egyedi rekordok létrehozására és szerkesztésére használják.

Gyökérelemük a <form>. Magas szintű szerkezeti elemekből (csoportok, jegyzetfüzetek) és interaktív elemekből (gombok és mezők) állnak:

<form string="Idea form">
    <group colspan="4">
        <group colspan="2" col="2">
            <separator string="General stuff" colspan="2"/>
            <field name="name"/>
            <field name="inventor_id"/>
        </group>

        <group colspan="2" col="2">
            <separator string="Dates" colspan="2"/>
            <field name="active"/>
            <field name="invent_date" readonly="1"/>
        </group>

        <notebook colspan="4">
            <page string="Description">
                <field name="description" nolabel="1"/>
            </page>
        </notebook>

        <field name="state"/>
    </group>
</form>

Exercise

Űrlap nézet testreszabása XML használatával

Hozzon létre saját űrlap nézetet a Tanfolyam objektumhoz. A megjelenítendő adatok: a tanfolyam neve és leírása legyenek.

Exercise

Jegyzetfüzetek

A Tanfolyam űrlap nézetben helyezze a leírás mezőt egy fül alá, hogy később könnyebb legyen további füleket hozzáadni, amelyek további információkat tartalmaznak.

Az űrlap nézetek egyszerű HTML-t is használhatnak a rugalmasabb elrendezésekhez:

<form string="Idea Form">
    <header>
        <button string="Confirm" type="object" name="action_confirm"
                invisible="state != 'draft'" class="oe_highlight" />
        <button string="Mark as done" type="object" name="action_done"
                invisible="state != 'confirmed'" class="oe_highlight"/>
        <button string="Reset to draft" type="object" name="action_draft"
                invisible="state not in ['confirmed', 'done']" />
        <field name="state" widget="statusbar"/>
    </header>
    <sheet>
        <div class="oe_title">
            <label for="name" class="oe_edit_only" string="Idea Name" />
            <h1><field name="name" /></h1>
        </div>
        <separator string="General" colspan="2" />
        <group colspan="2" col="2">
            <field name="description" placeholder="Idea description..." />
        </group>
    </sheet>
</form>

Keresési nézetek

A keresési nézetek testreszabják a lista nézethez (és más összesített nézetekhez) társított keresőmezőt. Gyökérelemük a <search> és mezőkből állnak, amelyek meghatározzák, mely mezőkben lehet keresni:

<search>
    <field name="name"/>
    <field name="inventor_id"/>
</search>

Ha a modellhez nem létezik keresési nézet, az Odoo generál egyet, amely csak a name mezőben való keresést engedélyezi.

Exercise

Tanfolyamok keresése

Engedélyezze a tanfolyamok keresését címük vagy leírásuk alapján.

Kapcsolatok a modellek között

Egy modell rekordja kapcsolatban állhat egy másik modell rekordjával. Például egy értékesítési rendelés rekord kapcsolatban áll egy ügyfél rekorddal, amely tartalmazza az ügyfél adatait; továbbá kapcsolatban áll az értékesítési rendelés sorainak rekordjaival is.

Exercise

Hozzon létre egy munkamenet modellt

Az Open Academy modulhoz egy munkamenetek modellt veszünk figyelembe: egy munkamenet egy tanfolyam egy adott időpontban, egy adott közönség számára történő megtartása.

Hozzon létre egy modellt a munkamenetek számára. Egy munkamenetnek van neve, kezdési dátuma, időtartama és ülőhelyek száma. Adjon hozzá egy műveletet és egy menüpontot a megjelenítésükhöz. Tegye az új modellt láthatóvá egy menüpont segítségével.

Relációs mezők

A relációs mezők rekordokat kapcsolnak össze, akár ugyanazon modell (hierarchiák), akár különböző modellek között.

A relációs mezőtípusok a következők:

Many2one(other_model, ondelete='set null')

Egy egyszerű hivatkozás egy másik objektumra:

print(foo.other_id.name)

Lásd még

idegen kulcsok

One2many(other_model, related_field)

Egy virtuális kapcsolat, a Many2one inverze. A One2many úgy viselkedik, mint egy rekordok tárolója, hozzáféréskor egy (esetleg üres) rekordhalmazt eredményez:

for other in foo.other_ids:
    print(other.name)

Veszély

Mivel a One2many egy virtuális kapcsolat, kell lennie egy Many2one mezőnek a other_model-ben, és a neve kell, hogy legyen related_field

Many2many(other_model)

Kétirányú többszörös kapcsolat, bármelyik oldalon lévő rekord kapcsolódhat a másik oldalon lévő bármennyi rekordhoz. Úgy viselkedik, mint egy rekordok tárolója, hozzáféréskor szintén egy esetleg üres rekordhalmazt eredményez:

for other in foo.other_ids:
    print(other.name)

Exercise

Many2one kapcsolatok

Egy many2one használatával módosítsa a Course és Session modelleket, hogy tükrözzék kapcsolatukat más modellekkel:

  • Egy kurzusnak van egy felelős felhasználója; ennek a mezőnek az értéke a beépített res.users modell egy rekordja.

  • Egy szekciónak van egy oktatója; ennek a mezőnek az értéke a beépített res.partner modell egy rekordja.

  • Egy szekció egy kurzushoz kapcsolódik; ennek a mezőnek az értéke az openacademy.course modell egy rekordja, és kötelező.

  • Alkalmazza a nézeteket.

Exercise

Fordított one2many kapcsolatok

A fordított one2many relációs mező használatával módosítsa a modelleket, hogy tükrözzék a kurzusok és szekciók közötti kapcsolatot.

Exercise

Többszörös many2many kapcsolatok

A many2many relációs mező használatával módosítsa a Session modellt, hogy minden szekciót összekapcsoljon egy résztvevők halmazával. A résztvevők partner rekordokkal lesznek ábrázolva, így a beépített res.partner modellhez kapcsolódunk. Ennek megfelelően módosítsa a nézeteket.

Öröklés

Modell öröklés

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 egy modul számára, hogy módosítsa egy másik modulban definiált modell viselkedését:

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

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

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

  • metódusok hozzáadása egy modellhez,

  • létező metódusok felülírása egy modellen.

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

../../_images/inheritance_methods.png

Lásd még

  • _inherit

  • _inherits

Nézet öröklés

Instead of modifying existing views in place (by overwriting them), Odoo provides view inheritance where children „extension” views are applied on top of root views, and can add or remove content from their parent.

Egy kiterjesztési nézet a szülőjére az inherit_id mező használatával hivatkozik, és egyetlen nézet helyett az arch mezője bármennyi xpath elemből áll, amelyek kiválasztják és módosítják a szülő nézet tartalmát:

<!-- improved idea categories list -->
<record id="idea_category_list2" model="ir.ui.view">
    <field name="name">id.category.list2</field>
    <field name="model">idea.category</field>
    <field name="inherit_id" ref="id_category_list"/>
    <field name="arch" type="xml">
        <!-- find field description and add the field
             idea_ids after it -->
        <xpath expr="//field[@name='description']" position="after">
          <field name="idea_ids" string="Number of ideas"/>
        </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 az egyező 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 speciális attribute elemek használatával az xpath törzsében

Javaslat

Egyetlen elem egyezésekor a position attribútum közvetlenül beállítható a megtalálandó elemre. Mindkét alábbi ö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>

Exercise

Meglévő tartalom módosítása

  • Modell öröklés használatával módosítsa a meglévő Partner modellt, hogy hozzáadjon egy instructor logikai mezőt, és egy many2many mezőt, amely megfelel a session-partner kapcsolatnak

  • Nézet öröklés használatával jelenítse meg ezeket a mezőket a partner űrlap nézetben

Domainek

Az Odoo-ban a Keresési tartományok értékek, amelyek feltételeket kódolnak a rekordokra. Egy domain egy kritériumlista, amelyet egy modell rekordjainak részhalmazának kiválasztására használnak. Minden kritérium egy hármas, amely tartalmaz egy mezőnevet, egy operátort és egy értéket.

Például, amikor a Product modellen használják, a következő domain kiválasztja az összes szolgáltatást, amelynek egységára meghaladja az 1000-et:

[('product_type', '=', 'service'), ('unit_price', '>', 1000)]

By default criteria are combined with an implicit AND. The logical operators & (AND), | (OR) and ! (NOT) can be used to explicitly combine criteria. They are used in prefix position (the operator is inserted before its arguments rather than between). For instance to select products „which are services OR have a unit price which is NOT between 1000 and 2000”:

['|',
    ('product_type', '=', 'service'),
    '!', '&',
        ('unit_price', '>=', 1000),
        ('unit_price', '<', 2000)]

Egy domain paraméter hozzáadható a relációs mezőkhöz, hogy korlátozza az érvényes rekordokat a kapcsolat számára, amikor rekordokat próbál kiválasztani az ügyfél felületén.

Exercise

Relációs mezőkön lévő domainek

Amikor egy Session oktatóját választja ki, csak az oktatók (partnerek, akiknél az instructor True-ra van állítva) legyenek láthatóak.

Exercise

Összetettebb domainek

Hozzon létre új partnerkategóriákat Tanár / 1. szint és Tanár / 2. szint. Egy foglalkozás oktatója lehet oktató vagy tanár (bármely szinten).

Számított mezők és alapértelmezett értékek

Eddig a mezők közvetlenül az adatbázisban voltak tárolva és onnan lettek lekérdezve. A mezők lehetnek számítottak is. Ebben az esetben a mező értéke nem az adatbázisból kerül lekérdezésre, hanem a modell egy metódusának meghívásával kerül kiszámításra.

Számított mező létrehozásához hozzon létre egy mezőt, és állítsa be annak compute attribútumát egy metódus nevére. A számítási metódusnak egyszerűen be kell állítania a mező értékét minden rekord esetében self-ben.

Veszély

self egy gyűjtemény

Az objektum self egy rekordhalmaz, azaz egy rendezett rekordgyűjtemény. Támogatja a szokásos Python műveleteket gyűjteményeken, mint például a len(self) és iter(self), valamint további halmazműveleteket, mint a recs1 + recs2.

A self feletti iterálás egyesével adja a rekordokat, ahol minden rekord maga is egy 1 méretű gyűjtemény. Egyedi rekordok mezőihez pontjelöléssel férhet hozzá/adhat értéket, mint például record.name.

import random
from odoo import models, fields, api

class ComputedModel(models.Model):
    _name = 'test.computed'

    name = fields.Char(compute='_compute_name')

    def _compute_name(self):
        for record in self:
            record.name = str(random.randint(1, 1e6))

Függőségek

Egy számított mező értéke általában más mezők értékeitől függ a számított rekordon. Az ORM elvárja, hogy a fejlesztő megadja ezeket a függőségeket a számítási metóduson a depends() dekorátorral. A megadott függőségeket az ORM használja a mező újraszámításának kiváltására, amikor valamelyik függősége módosult:

from odoo import models, fields, api

class ComputedModel(models.Model):
    _name = 'test.computed'

    name = fields.Char(compute='_compute_name')
    value = fields.Integer()

    @api.depends('value')
    def _compute_name(self):
        for record in self:
            record.name = "Record with value %s" % record.value

Exercise

Számított mezők

  • Adja hozzá a foglalt helyek százalékát a Session modellhez

  • Display that field in the list and form views

  • Jelenítse meg a mezőt haladási sávként

Alapértelmezett értékek

Bármely mezőhöz megadható alapértelmezett érték. A mező definíciójában adja hozzá a default=X opciót, ahol X lehet egy Python literál érték (logikai, egész, lebegőpontos, szöveg), vagy egy függvény, amely egy rekordhalmazt vesz át és egy értéket ad vissza:

name = fields.Char(default="Unknown")
user_id = fields.Many2one('res.users', default=lambda self: self.env.user)

Megjegyzés

Az objektum self.env hozzáférést biztosít a kérés paramétereihez és más hasznos dolgokhoz:

  • A self.env.cr vagy self._cr az adatbázis kurzor objektuma; az adatbázis lekérdezésére használják

  • A self.env.uid vagy self._uid az aktuális felhasználó adatbázis azonosítója

  • A self.env.user az aktuális felhasználó rekordja

  • A self.env.context vagy self._context a kontextus szótár

  • self.env.ref(xml_id) visszaadja az XML azonosítóhoz tartozó rekordot

  • self.env[model_name] visszaadja a megadott modell példányát

Exercise

Aktív objektumok – Alapértelmezett értékek

  • Határozza meg a start_date alapértelmezett értékét a mai napként (lásd Date).

  • Adjon hozzá egy active mezőt a Session osztályhoz, és állítsa be az üléseket alapértelmezés szerint aktívként.

Változás esetén

The „onchange” mechanism provides a way for the client interface to update a form whenever the user has filled in a value in a field, without saving anything to the database.

Például, tegyük fel, hogy egy modellnek három mezője van: amount, unit_price és price, és azt szeretné, hogy az ár frissüljön a űrlapon, amikor bármelyik másik mező módosul. Ehhez definiáljon egy metódust, ahol self a rekordot képviseli a űrlap nézetben, és díszítse azt onchange()-val, hogy megadja, melyik mezőnél kell aktiválódnia. Bármilyen változtatás, amit self-en végez, tükröződni fog a űrlapon.

<!-- content of form view -->
<field name="amount"/>
<field name="unit_price"/>
<field name="price" readonly="1"/>
# onchange handler
@api.onchange('amount', 'unit_price')
def _onchange_price(self):
    # set auto-changing field
    self.price = self.amount * self.unit_price
    # Can optionally return a warning and domains
    return {
        'warning': {
            'title': "Something bad happened",
            'message': "It was very bad indeed",
        }
    }

A számított mezők esetében az onchange viselkedés beépített, ahogy az a Session űrlap használatával látható: változtassa meg az ülések vagy résztvevők számát, és a taken_seats folyamatjelző automatikusan frissül.

Exercise

Figyelmeztetés

Adjon hozzá egy explicit onchange-t, hogy figyelmeztessen az érvénytelen értékekre, mint például a negatív ülésszám, vagy több résztvevő, mint ülés.

Modell korlátozások

Az Odoo két módot biztosít az automatikusan ellenőrzött invariánsok beállítására: Python korlátozások és SQL korlátozások.

A Python korlátozás egy olyan metódusként van definiálva, amelyet constrains() dekorátorral látnak el, és egy rekordhalmazon hívnak meg. A dekorátor meghatározza, hogy mely mezők vesznek részt a korlátozásban, így a korlátozás automatikusan kiértékelésre kerül, amikor valamelyikük módosul. A metódusnak kivételt kell dobnia, ha az invariáns nem teljesül:

from odoo.exceptions import ValidationError

@api.constrains('age')
def _check_something(self):
    for record in self:
        if record.age > 20:
            raise ValidationError("Your record is too old: %s" % record.age)
    # all records passed the test, don't return anything

Exercise

Python korlátozások hozzáadása

Adjon hozzá egy korlátozást, amely ellenőrzi, hogy az oktató nincs jelen a saját foglalkozásának résztvevői között.

Az SQL korlátozások a modell attribútumon keresztül vannak definiálva _sql_constraints. Ez utóbbi egy hármas stringek listájához van rendelve (név, sql_definíció, üzenet), ahol a név egy érvényes SQL korlátozás neve, az sql_definíció egy table_constraint kifejezés, és az üzenet a hibaüzenet.

Exercise

SQL korlátozások hozzáadása

A PostgreSQL dokumentáció segítségével adja hozzá a következő korlátozásokat:

  1. ELLENŐRIZZE, hogy a kurzus leírása és a kurzus címe különbözőek

  2. Tegye a kurzus nevét EGYEDIVÉ

Exercise

Exercise 6 - Add a duplicate option

Since we added a constraint for the Course name uniqueness, it is not possible to use the „duplicate” function anymore (Form ‣ Duplicate).

Re-implement your own „copy” method which allows to duplicate the Course object, changing the original name into „Copy of [original name]”.

Haladó nézetek

list views

list views can take supplementary attributes to further customize their behavior:

decoration-{$name}

lehetővé teszi a sor szövegének stílusának megváltoztatását a megfelelő rekord attribútumai alapján.

Az értékek Python kifejezések. Minden rekord esetében a kifejezés a rekord attribútumaival mint kontextusértékekkel kerül kiértékelésre, és ha true, a megfelelő stílus alkalmazásra kerül a sorra. Íme néhány más elérhető érték a kontextusban:

  • uid: az aktuális felhasználó azonosítója,

  • today: az aktuális helyi dátum, mint YYYY-MM-DD formátumú karakterlánc,

  • now: ugyanaz, mint a today, az aktuális idő hozzáadásával. Ez az érték ÉÉÉÉ-HH-NN óó:pp:mp formátumban van.

{$name} lehet bf (font-weight: bold), it (font-style: italic), vagy bármely bootstrap kontextuális szín (danger, info, muted, primary, success vagy warning).

<list string="Idea Categories" decoration-info="state=='draft'"
    decoration-danger="state=='trashed'">
    <field name="name"/>
    <field name="state"/>
</list>
editable

Either "top" or "bottom". Makes the list view editable in-place (rather than having to go through the form view), the value is the position where new rows appear.

Exercise

Lista színezése

Modify the Session list view in such a way that sessions lasting less than 5 days are colored blue, and the ones lasting more than 15 days are colored red.

Naptárak

Rekordokat jelenít meg naptári eseményekként. Gyökérelemük <calendar>, és leggyakoribb attribútumaik:

color

A mező neve, amelyet szín szegmentálásra használnak. A színek automatikusan kiosztásra kerülnek az eseményekhez, de az azonos szín szegmensben lévő események (azok a rekordok, amelyeknek az @color mezőjük azonos értékkel bír) ugyanazt a színt kapják.

date_start

a rekord mezője, amely az esemény kezdő dátumát/időpontját tartalmazza

date_stop (opcionális)

a rekord mezője, amely az esemény befejező dátumát/időpontját tartalmazza

string

a rekord mezője, amely meghatározza az egyes naptári események címkéjét

<calendar string="Ideas" date_start="invent_date" color="inventor_id">
    <field name="name"/>
</calendar>

Exercise

Naptár nézet

Adjon hozzá egy Naptár nézetet a Session modellhez, lehetővé téve a felhasználó számára, hogy megtekintse az Open Academy-hoz kapcsolódó eseményeket.

Keresési nézetek

A Keresés nézet <field> elemei rendelkezhetnek @filter_domain-nal, amely felülírja a megadott mező keresésére generált domaint. A megadott domainben a self a felhasználó által megadott értéket képviseli. Az alábbi példában mind a name, mind a description mezőkön való kereséshez használják.

A Keresés nézetek tartalmazhatnak <filter> elemeket is, amelyek előre definiált keresések kapcsolóiként működnek. A szűrőknek az alábbi attribútumok egyikével kell rendelkezniük:

domain

adja hozzá a megadott domaint az aktuális kereséshez

context

adjon hozzá némi kontextust az aktuális kereséshez; használja a group_by kulcsot az eredmények csoportosításához a megadott mezőnév alapján

<search string="Ideas">
    <field name="name"/>
    <field name="description" string="Name and description"
           filter_domain="['|', ('name', 'ilike', self), ('description', 'ilike', self)]"/>
    <field name="inventor_id"/>
    <field name="country_id" widget="selection"/>

    <filter name="my_ideas" string="My Ideas"
            domain="[('inventor_id', '=', uid)]"/>
    <group string="Group By">
        <filter name="group_by_inventor" string="Inventor"
                context="{'group_by': 'inventor_id'}"/>
    </group>
</search>

Ahhoz, hogy egy nem alapértelmezett keresési nézetet használjon egy műveletben, azt a műveleti rekord search_view_id mezőjével kell összekapcsolni.

A művelet alapértelmezett értékeket is beállíthat a keresési mezőkhöz a context mezőjén keresztül: a search_default_field_name formátumú kontextuskulcsok a field_name mezőt a megadott értékkel inicializálják. A keresési szűrőknek opcionális @name-nel kell rendelkezniük, hogy alapértelmezettként működjenek, és logikai értékként viselkedjenek (csak alapértelmezettként engedélyezhetők).

Exercise

Keresési nézetek

  1. Adjon hozzá egy gombot, amely kiszűri azokat a kurzusokat, amelyekért az aktuális felhasználó a felelős a kurzus keresési nézetben. Alapértelmezettként legyen kiválasztva.

  2. Adjon hozzá egy gombot, amely a kurzusokat a felelős felhasználó szerint csoportosítja.

Gantt

Figyelem

A gantt nézethez szükséges a web_gantt modul, amely a enterprise edition verzióban található.

A vízszintes sávdiagramokat általában projekttervezés és előrehaladás bemutatására használják, gyökérelemük a <gantt>.

<gantt string="Ideas"
       date_start="invent_date"
       date_stop="date_finished"
       progress="progress"
       default_group_by="inventor_id" />

Exercise

Gantt diagramok

Adjon hozzá egy Gantt diagramot, amely lehetővé teszi a felhasználó számára, hogy megtekintse az Open Academy modulhoz kapcsolódó ülések ütemezését. Az üléseket oktató szerint kell csoportosítani.

Grafikon nézetek

A grafikon nézetek lehetővé teszik a modellek összesített áttekintését és elemzését, gyökérelemük a <graph>.

Megjegyzés

A pivot nézetek (<pivot> elem) egy többdimenziós táblázat, amely lehetővé teszi a szűrők és dimenziók kiválasztását a megfelelő összesített adathalmaz eléréséhez, mielőtt áttérnénk egy grafikusabb áttekintésre. A pivot nézet ugyanazt a tartalomdefiníciót osztja meg, mint a grafikon nézetek.

A grafikon nézeteknek 4 megjelenítési módja van, az alapértelmezett módot a @type attribútummal lehet kiválasztani.

Oszlop (alapértelmezett)

egy oszlopdiagram, az első dimenziót használják a csoportok meghatározására a vízszintes tengelyen, más dimenziók az egyes csoportokon belüli összesített oszlopokat határozzák meg.

By default bars are side-by-side, they can be stacked by using @stacked="True" on the <graph>

Vonal

2-dimenziós vonaldiagram

Torta

2-dimenziós torta

A grafikon nézetek tartalmazzák a <field> elemet, amely kötelező @type attribútummal rendelkezik, amely az alábbi értékeket veheti fel:

row (alapértelmezett)

a mezőt alapértelmezés szerint aggregálni kell

measure

a mezőt inkább aggregálni kell, mint csoportosítani

<graph string="Total idea score by Inventor">
    <field name="inventor_id"/>
    <field name="score" type="measure"/>
</graph>

Figyelem

A grafikon nézetek aggregációkat hajtanak végre az adatbázis értékein, nem működnek nem tárolt számított mezőkkel.

Exercise

Grafikon nézet

Adjon hozzá egy grafikon nézetet a Session objektumhoz, amely minden tanfolyamhoz megjeleníti a résztvevők számát oszlopdiagram formájában.

Kanban

Feladatok, gyártási folyamatok stb. szervezésére használják… gyökérelemük a <kanban>.

A kanban nézet egy kártyakészletet mutat, amely oszlopokba csoportosítható. Minden kártya egy rekordot képvisel, és minden oszlop egy aggregációs mező értékeit.

Például a projektfeladatok szakaszok szerint szervezhetők (minden oszlop egy szakasz), vagy felelős szerint (minden oszlop egy felhasználó), és így tovább.

A kanban nézetek minden kártya szerkezetét form elemek (beleértve az alapvető HTML-t) és QWeb sablonok keverékeként határozzák meg.

Exercise

Kanban nézet

Adjon hozzá egy Kanban nézetet, amely a kurzusok szerint csoportosítva jeleníti meg az üléseket (az oszlopok tehát a kurzusok).

Biztonság

A hozzáférés-ellenőrzési mechanizmusokat úgy kell konfigurálni, hogy koherens biztonsági politikát érjenek el.

Csoportalapú hozzáférés-ellenőrzési mechanizmusok

A csoportok normál rekordként jönnek létre a res.groups modellen, és menüdefiníciók révén kapnak menühozzáférést. Azonban még menü nélkül is, az objektumok közvetetten elérhetők lehetnek, ezért tényleges objektumszintű jogosultságokat (olvasás, írás, létrehozás, törlés) kell meghatározni a csoportok számára. Ezeket általában CSV fájlokban helyezik el a modulokban. Lehetőség van arra is, hogy korlátozzák a hozzáférést egy nézet vagy objektum meghatározott mezőihez a mező csoportok attribútumának használatával.

Hozzáférési jogok

A hozzáférési jogok az ir.model.access modell rekordjaiként vannak meghatározva. Minden hozzáférési jog egy modellhez, egy csoporthoz (vagy globális hozzáférés esetén csoport nélkül), és egy jogosultságkészlethez kapcsolódik: olvasás, írás, létrehozás, törlés. Az ilyen hozzáférési jogokat általában a modell nevét viselő CSV fájl hozza létre: ir.model.access.csv.

id,name,model_id/id,group_id/id,perm_read,perm_write,perm_create,perm_unlink
access_idea_idea,idea.idea,model_idea_idea,base.group_user,1,1,1,0
access_idea_vote,idea.vote,model_idea_vote,base.group_user,1,1,1,0

Exercise

Hozzáférés-ellenőrzés hozzáadása az Odoo felületén keresztül

Create a new user „John Smith”. Then create a group „OpenAcademy / Session Read” with read access to the Session model.

Exercise

Hozzáférés-ellenőrzés hozzáadása az adatok fájlokon keresztül a modulban

Adatfájlok használata,

  • Hozzon létre egy OpenAcademy / Manager csoportot, amely teljes hozzáférést biztosít az összes OpenAcademy modellhez

  • Tegye a Session és Course modelleket olvashatóvá minden felhasználó számára

Rekordszabályok

Egy rekordszabály korlátozza a hozzáférési jogokat a megadott modell rekordjainak egy részhalmazára. Egy szabály az ir.rule modell egy rekordja, és egy modellhez, csoportok számához (many2many mező), a korlátozásra vonatkozó engedélyekhez és egy tartományhoz kapcsolódik. A tartomány meghatározza, hogy mely rekordokra korlátozódnak a hozzáférési jogok.

Itt egy példa egy szabályra, amely megakadályozza a nem cancel állapotú leadek törlését. Vegye észre, hogy a groups mező értékének követnie kell ugyanazt a konvenciót, mint az ORM write() metódusa.

<record id="delete_cancelled_only" model="ir.rule">
    <field name="name">Only cancelled leads may be deleted</field>
    <field name="model_id" ref="crm.model_crm_lead"/>
    <field name="groups" eval="[(4, ref('sales_team.group_sale_manager'))]"/>
    <field name="perm_read" eval="0"/>
    <field name="perm_write" eval="0"/>
    <field name="perm_create" eval="0"/>
    <field name="perm_unlink" eval="1" />
    <field name="domain_force">[('state','=','cancel')]</field>
</record>

Exercise

Rekordszabály

Add a record rule for the model Course and the group „OpenAcademy / Manager”, that restricts write and unlink accesses to the responsible of a course. If a course has no responsible, all users of the group must be able to modify it.

Varázslók

A varázslók interaktív munkameneteket írnak le a felhasználóval (vagy párbeszédablakokkal) dinamikus űrlapokon keresztül. Egy varázsló egyszerűen egy modell, amely a TransientModel osztályt bővíti a Model helyett. A TransientModel osztály bővíti a Model osztályt, és újrahasznosítja annak meglévő mechanizmusait, a következő sajátosságokkal:

  • A varázsló rekordok nem tartósak; automatikusan törlődnek az adatbázisból egy bizonyos idő után. Ezért nevezik őket átmenetinek.

  • A varázsló rekordok hivatkozhatnak normál rekordokra vagy varázsló rekordokra relációs mezőkön (many2one vagy many2many) keresztül, de a normál rekordok nem hivatkozhatnak varázsló rekordokra many2one mezőn keresztül.

Szeretnénk létrehozni egy varázslót, amely lehetővé teszi a felhasználók számára, hogy résztvevőket hozzanak létre egy adott üléshez, vagy egyszerre több üléshez.

Exercise

Határozza meg a varázslót

Hozzon létre egy varázsló modellt, amely many2one kapcsolatban áll a Session modellel és many2many kapcsolatban a Partner modellel.

Varázslók indítása

A varázslók egyszerűen ablak műveletek egy target mezővel, amelynek értéke new, ami megnyitja a nézetet (általában egy űrlapot) egy külön párbeszédablakban. A művelet indítható egy menüelemen keresztül, de általában egy gomb által van indítva.

An other way to launch wizards is through the Action menu of a list or form view. This is done through the binding_model_id field of the action. Setting this field will make the action appear on the views of the model the action is „bound” to.

<record id="launch_the_wizard" model="ir.actions.act_window">
    <field name="name">Launch the Wizard</field>
    <field name="res_model">wizard.model.name</field>
    <field name="view_mode">form</field>
    <field name="target">new</field>
    <field name="binding_model_id" ref="model_context_model_ref"/>
</record>

Javaslat

While wizards use regular views and buttons, normally clicking any button in a form would first save the form then close the dialog. Because this is often undesirable in wizards, a special attribute special="cancel" is available which immediately closes the wizard without saving the form.

Exercise

Indítsa el a varázslót

  1. Határozzon meg egy űrlap nézetet a varázslóhoz.

  2. Adja hozzá a műveletet, hogy elindítsa azt a Session modell kontextusában.

  3. Határozzon meg egy alapértelmezett értéket a varázsló ülés mezőjéhez; használja a self._context kontextus paramétert az aktuális ülés lekéréséhez.

Exercise

Résztvevők regisztrálása

Adjon hozzá gombokat a varázslóhoz, és valósítsa meg a megfelelő módszert a résztvevők hozzáadására a megadott szekcióhoz.

Exercise

Résztvevők regisztrálása több szekcióra

Módosítsa a varázsló modellt úgy, hogy a résztvevők több szekcióra is regisztrálhatók legyenek.

Nemzetköziesítés

Minden modul biztosíthatja saját fordításait az i18n könyvtárban, olyan fájlokkal, amelyek neve LANG.po, ahol LANG a nyelvi kód, vagy a nyelv és ország kombinációja, ha különböznek (pl. pt.po vagy pt_BR.po). Az Odoo automatikusan betölti a fordításokat minden engedélyezett nyelvhez. A fejlesztők mindig angolt használnak modul létrehozásakor, majd exportálják a modul kifejezéseit az Odoo gettext POT export funkciójával (Beállítások ‣ Fordítások ‣ Import/Export ‣ Fordítás exportálása nyelv megadása nélkül), hogy létrehozzák a modul sablon POT fájlt, majd ebből származtatják a fordított PO fájlokat. Számos IDE rendelkezik bővítményekkel vagy módokkal a PO/POT fájlok szerkesztésére és egyesítésére.

Javaslat

The Portable Object files generated by Odoo are published on Odoo’s Translations Platform, making it easy to translate the software.

|- idea/ # The module directory
   |- i18n/ # Translation files
      | - idea.pot # Translation Template (exported from Odoo)
      | - fr.po # French translation
      | - pt_BR.po # Brazilian Portuguese translation
      | (...)

Javaslat

By default Odoo’s POT export only extracts labels inside XML files or inside field definitions in Python code, but any Python string can be translated this way by surrounding it with the function odoo._() (e.g. _("Label"))

Exercise

Egy modul fordítása

Válasszon egy második nyelvet az Odoo telepítéséhez. Fordítsa le a modulját az Odoo által biztosított eszközökkel.

Riportolás

Nyomtatott jelentések

Az Odoo egy jelentésmotort használ, amely a QWeb sablonok, Twitter Bootstrap és Wkhtmltopdf alapjaira épül.

Egy jelentés két elem kombinációja:

  • egy ir.actions.report, amely különböző alapvető paramétereket konfigurál a jelentéshez (alapértelmezett típus, hogy a jelentést a generálás után el kell-e menteni az adatbázisba,…)

    <record id="account_invoices" model="ir.actions.report">
        <field name="name">Invoices</field>
        <field name="model">account.invoice</field>
        <field name="report_type">qweb-pdf</field>
        <field name="report_name">account.report_invoice</field>
        <field name="report_file">account.report_invoice</field>
        <field name="attachment_use" eval="True"/>
        <field name="attachment">(object.state in ('open','paid')) and
            ('INV'+(object.number or '').replace('/','')+'.pdf')</field>
        <field name="binding_model_id" ref="model_account_invoice"/>
        <field name="binding_type">report</field>
    </record>
    

    Javaslat

    Because it largerly a standard action, as with Varázslók it is generally useful to add the report as a contextual item on the list and / or form views of the model being reported on via the binding_model_id field.

    Itt a binding_type-ot is használjuk annak érdekében, hogy a jelentés a jelentés környezeti menüben legyen, nem pedig az akció menüben. Nincs technikai különbség, de az elemek megfelelő helyre helyezése segíti a felhasználókat.

  • Egy szabványos QWeb nézet a tényleges jelentéshez:

    <t t-call="web.html_container">
        <t t-foreach="docs" t-as="o">
            <t t-call="web.external_layout">
                <div class="page">
                    <h2>Report title</h2>
                </div>
            </t>
        </t>
    </t>
    

    a szabványos renderelési környezet számos elemet biztosít, amelyek közül a legfontosabbak:

    docs

    azok a rekordok, amelyekhez a jelentést nyomtatják

    user

    a jelentést nyomtató felhasználó

Mivel a jelentések szabványos weboldalak, elérhetők egy URL-en keresztül, és a kimeneti paraméterek manipulálhatók ezen az URL-en keresztül. Például az Invoice jelentés HTML verziója elérhető a http://localhost:8069/report/html/account.report_invoice/1 címen (ha az account telepítve van), és a PDF verzió a http://localhost:8069/report/pdf/account.report_invoice/1 címen.

Veszély

Ha úgy tűnik, hogy a PDF jelentéséből hiányoznak a stílusok (azaz a szöveg megjelenik, de a stílus/elrendezés eltér az html verziótól), valószínűleg a wkhtmltopdf folyamat nem éri el a webszervert, hogy letöltse azokat.

Ha ellenőrzi a szerver naplóit, és látja, hogy a CSS stílusok nem töltődnek le PDF jelentés generálásakor, akkor ez a probléma legvalószínűbb oka.

A wkhtmltopdf folyamat a web.base.url rendszerparamétert fogja használni, mint gyökér útvonal az összes kapcsolt fájlhoz, de ez a paraméter automatikusan frissül minden alkalommal, amikor az Adminisztrátor bejelentkezik. Ha a szervere valamilyen proxy mögött található, amely nem elérhető, akkor ez problémát okozhat. Ezt úgy javíthatja ki, hogy hozzáadja az alábbi rendszerparaméterek egyikét:

  • report.url, amely egy, a szerveréről elérhető URL-re mutat (valószínűleg http://localhost:8069 vagy valami hasonló). Ez kizárólag erre a célra lesz használva.

  • web.base.url.freeze, ha True-ra van állítva, megállítja a web.base.url automatikus frissítéseit.

Exercise

Jelentés létrehozása a Session modellhez

Minden egyes munkamenethez meg kell jeleníteni a munkamenet nevét, kezdetét és végét, valamint a munkamenet résztvevőinek listáját.

Irányítópultok

Exercise

Irányítópult meghatározása

Határozzon meg egy irányítópultot, amely tartalmazza az Ön által létrehozott grafikon nézetet, az ülések naptár nézetét és a kurzusok listanézetét (amely átváltható űrlap nézetre). Ez az irányítópult elérhető legyen a menüben egy menüelemen keresztül, és automatikusan megjelenjen a web kliensben, amikor az OpenAcademy főmenü ki van választva.

1

lehetséges bizonyos mezők automatikus létrehozásának letiltása

2

nyers SQL lekérdezések írása lehetséges, de óvatosságot igényel, mivel megkerüli az összes Odoo hitelesítési és biztonsági mechanizmust.