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:
nézetek vagy jelentések,
konfigurációs adatok (modulok paraméterezése, biztonsági szabályok),
bemutató adatok
és még sok más
- 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
modelaz Odoo modell neve a rekordhoz.Az
idegy 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 egynameattribú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.
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
One2many(other_model, related_field)Egy virtuális kapcsolat, a
Many2oneinverze. AOne2manyú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
One2manyegy virtuális kapcsolat, kell lennie egyMany2onemezőnek aother_model-ben, és a neve kell, hogy legyenrelated_fieldMany2many(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.usersmodell egy rekordja.Egy szekciónak van egy oktatója; ennek a mezőnek az értéke a beépített
res.partnermodell egy rekordja.Egy szekció egy kurzushoz kapcsolódik; ennek a mezőnek az értéke az
openacademy.coursemodell 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.
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>
exprEgy 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
positionMűvelet, amelyet az egyező elemre kell alkalmazni:
insidehozzáfűzi az
xpathtörzsét az egyező elem végéhezreplaceaz egyező elemet az
xpathtörzsével helyettesíti, az új törzs bármely$0csomópont előfordulását az eredeti elemmel helyettesítvebeforeaz
xpathtörzsét testvérként beszúrja az egyező elem eléafteraz
xpathstörzsét testvérként beszúrja az egyező elem utánattributesmódosítja a megfelelő elem attribútumait speciális
attributeelemek használatával azxpathtö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
instructorlogikai mezőt, és egy many2many mezőt, amely megfelel a session-partner kapcsolatnakNé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.crvagyself._craz adatbázis kurzor objektuma; az adatbázis lekérdezésére használjákA
self.env.uidvagyself._uidaz aktuális felhasználó adatbázis azonosítójaA
self.env.useraz aktuális felhasználó rekordjaA
self.env.contextvagyself._contexta 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
activemező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:
ELLENŐRIZZE, hogy a kurzus leírása és a kurzus címe különbözőek
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 ().
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, mintYYYY-MM-DDformátumú karakterlánc,now: ugyanaz, mint atoday, az aktuális idő hozzáadásával. Ez az értékÉÉÉÉ-HH-NN óó:pp:mpformátumban van.
{$name}lehetbf(font-weight: bold),it(font-style: italic), vagy bármely bootstrap kontextuális szín (danger,info,muted,primary,successvagywarning).<list string="Idea Categories" decoration-info="state=='draft'" decoration-danger="state=='trashed'"> <field name="name"/> <field name="state"/> </list>
editableEither
"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:
colorA 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
@colormezőjük azonos értékkel bír) ugyanazt a színt kapják.date_starta 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
stringa 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:
domainadja hozzá a megadott domaint az aktuális kereséshez
contextadjon hozzá némi kontextust az aktuális kereséshez; használja a
group_bykulcsot 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
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.
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
measurea 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 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
Határozzon meg egy űrlap nézetet a varázslóhoz.
Adja hozzá a műveletet, hogy elindítsa azt a Session modell kontextusában.
Határozzon meg egy alapértelmezett értéket a varázsló ülés mezőjéhez; használja a
self._contextkontextus 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 ( 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_idfield.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:
docsazok a rekordok, amelyekhez a jelentést nyomtatják
usera 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űleghttp://localhost:8069vagy valami hasonló). Ez kizárólag erre a célra lesz használva.web.base.url.freeze, haTrue-ra van állítva, megállítja aweb.base.urlautomatikus 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.