2. fejezet: Galéria nézet létrehozása¶
Nézzük meg, hogyan lehet teljesen a semmiből új nézetet létrehozni. Bizonyos értelemben nem túl nehéz megtenni, de nincsenek igazán jó források arra, hogyan kell ezt megtenni. Vegye figyelembe, hogy a legtöbb helyzetet egy meglévő nézet testreszabásával vagy egy kliens akcióval kell megoldani.
Ehhez a gyakorlathoz tegyük fel, hogy egy galéria nézetet szeretnénk létrehozni, amely lehetővé teszi számunkra, hogy egy rekordhalmazt egy képmezővel ábrázoljunk.
A problémát biztosan meg lehetne oldani egy kanban nézettel, de ez azt jelenti, hogy nem lehetséges a normál kanban nézetet és a galéria nézetet ugyanabban az akcióban használni.
Készítsünk egy galéria nézetet. Minden galéria nézetet egy image_field attribútum határoz meg az arch-ban:
<gallery image_field="some_field"/>
A fejezet feladatainak elvégzéséhez telepítenie kell az awesome_gallery bővítményt. Ez a bővítmény tartalmazza az új nézet hozzáadásához szükséges szerverfájlokat.
Cél
The solutions for each exercise of the chapter are hosted on the official Odoo tutorials repository.
1. Készítsen egy hello world nézetet¶
Az első lépés egy JavaScript megvalósítás létrehozása egy egyszerű komponenssel.
Hozza létre a
gallery_view.js,gallery_controller.jsésgallery_controller.xmlfájlokat astatic/srckönyvtárban.Valósítson meg egy egyszerű hello world komponenst a
gallery_controller.jsfájlban.A
gallery_view.jsfájlban importálja a vezérlőt, hozzon létre egy nézet objektumot, és regisztrálja azt a nézet regisztrációs táblábangallerynéven.Example
Íme egy példa arra, hogyan definiáljunk egy nézet objektumot:
import { registry } from "@web/core/registry"; import { MyController } from "./my_controller"; export const myView = { type: "my_view", display_name: "MyView", icon: "oi oi-view-list", multiRecord: true, Controller: MyController, }; registry.category("views").add("my_controller", myView);
Adja hozzá a
gallery-t a nézettípusok közé acontacts.action_contactsműveletben.Győződjön meg róla, hogy látható a hello world komponens, amikor átvált a galéria nézetre.
2. Használja a Layout komponenst¶
Eddig a galéria nézetünk nem hasonlít egy szabványos nézetre. Használjuk a Layout komponenst, hogy a szabványos funkciók elérhetők legyenek, mint más nézeteknél.
Importálja a
Layoutkomponenst, és adja hozzá aGalleryControllercomponentsrészéhez.Frissítse a sablont a
Layouthasználatára. Szüksége van egydisplaytulajdonságra, amely megtalálható aprops.display-ben.
3. Az arch elemzése¶
Jelenleg a galéria nézetünk nem sokat csinál. Kezdjük azzal, hogy elolvassuk a nézet arch-jában található információkat.
Az arch elemzésének folyamata általában egy ArchParser-rel történik, amely minden nézethez specifikus. Egy általános XMLParser osztályból öröklődik.
Example
Íme egy példa arra, hogyan nézhet ki egy ArchParser:
export class MyCustomArchParser {
parse(xmlDoc) {
const myAttribute = xmlDoc.getAttribute("my_attribute")
return {
myAttribute,
}
}
}
Hozza létre az
ArchParserosztályt saját fájljában.Használja az
image_fieldinformációk olvasására.Frissítse a
gallerynézet kódját, hogy hozzáadja azt a vezérlő által fogadott tulajdonságokhoz.
Megjegyzés
Valószínűleg kissé túlzás így csinálni, mivel alapvetően csak egy attribútumot kell kiolvasnunk az arch-ból, de ez egy olyan tervezés, amelyet minden más odoo nézet is használ, mivel lehetővé teszi, hogy néhány előfeldolgozást kivonjunk a vezérlőből.
Lásd még
4. Töltsünk be néhány adatot¶
Most szerezzünk valós adatokat a szerverről. Ehhez az orm szolgáltatás webSearchRead függvényét kell használnunk.
Example
Itt van egy példa egy webSearchRead hívásra, amely egy modell rekordjait kéri le:
const { length, records } = this.orm.webSearchRead(this.resModel, domain, {
specification: {
[this.fieldToFetch]: {},
[this.secondFieldToFetch]: {},
},
context: {
bin_size: true,
}
})
Adjon hozzá egy
loadImages(domain) {...}metódust aGalleryController-hez. Ennek végre kell hajtania egywebSearchReadhívást az orm szolgáltatásból, hogy lekérje a domainhez tartozó rekordokat, és használja a props-ban kapottimageFieldmezőt.Ha nem tartalmazza a
bin_size-t a hívás kontextusában, akkor az image mezőt base64 kódolásban kapja meg. Ügyeljen arra, hogy abin_size-t a kontextusba helyezze, hogy megkapja az image mező méretét. Az képet később fogjuk megjeleníteni.Módosítsa a
setupkódot, hogy hívja meg ezt a metódust azonWillStartésonWillUpdatePropshorgokban.Módosítsa a sablont, hogy megjelenítse az egyes képek azonosítóját és méretét a
Layoutkomponens alapértelmezett slotjában.
Megjegyzés
A betöltési adatkódot a következő gyakorlatban egy megfelelő modellbe fogjuk áthelyezni.
5. Oldja meg a párhuzamossági problémát¶
Jelenleg a kódunk nem védett a párhuzamosság ellen. Ha valaki kétszer változtatja meg a domaint, akkor kétszer fogja meghívni a loadImages(domain) függvényt. Így két kérésünk van, amelyek különböző időpontokban érkezhetnek meg, különböző tényezőktől függően. Ha az első kérés válaszát a második kérés válasza után kapjuk meg, az inkonzisztens állapothoz vezet.
Az Odoo KeepLast primitívje megoldja ezt a problémát, kezeli a feladatok listáját, és csak az utolsó feladatot tartja aktívan.
Importálja a
KeepLast-t a@web/core/utils/concurrencyfájlból.Példányosítson egy
KeepLastobjektumot a modellben.Adja hozzá a
webSearchReadhívást aKeepLast-hoz, hogy csak az utolsó hívás legyen megoldva.
Lásd még
6. Kód átszervezése¶
A valós nézetek egy kicsit szervezettebbek. Lehet, hogy ez túlzás ebben a példában, de az a cél, hogy megtanuljuk, hogyan kell struktúrálni a kódot az Odoo-ban. Emellett ez jobban fog méreteződni a változó követelményekkel.
Mozgassa az összes modellkódot a saját
GalleryModelosztályába.Mozgassa az összes renderelési kódot egy
GalleryRendererkomponensbe.Importálja a
GalleryModel-t és aGalleryRenderer-t aGalleryController-be, hogy működjön.
7. Tegye a nézetet kiterjeszthetővé¶
A nézet kiterjesztéséhez importálhatja a galéria nézet objektumot, hogy saját ízlésére módosítsa azt. A probléma az, hogy jelenleg nem lehet egyedi modellt vagy renderelőt definiálni, mert ezek a vezérlőben vannak kódolva.
Importálja a
GalleryModelésGalleryRendererelemeket a galéria nézet fájlba.Adjon hozzá egy
ModelésRendererkulcsot a galéria nézet objektumhoz, és rendelje hozzá őket aGalleryModelésGalleryRendererelemekhez. Adja át aModelésRendererelemeket tulajdonságként a vezérlőnek.Távolítsa el a vezérlőben kódolt importálást, és szerezze be őket a tulajdonságokból.
Használja a t-component elemet dinamikus alkomponensekhez.
Megjegyzés
Így lehet most kiterjeszteni a galéria nézetet a renderelő módosításával:
import { registry } from '@web/core/registry';
import { galleryView } from '@awesome_gallery/gallery_view';
import { GalleryRenderer } from '@awesome_gallery/gallery_renderer';
export class MyExtendedGalleryRenderer extends GalleryRenderer {
static template = "my_module.MyExtendedGalleryRenderer";
setup() {
super.setup();
console.log("my gallery renderer extension");
}
}
registry.category("views").add("my_gallery", {
...galleryView,
Renderer: MyExtendedGalleryRenderer,
});
8. Képek megjelenítése¶
Frissítse a renderelőt, hogy a képeket szép módon jelenítse meg, ha a mező be van állítva. Ha az image_field üres, akkor egy üres dobozt jelenítsen meg helyette.
Javaslat
Van egy vezérlő, amely lehetővé teszi, hogy képet kérjen le egy rekordból. Használhatja ezt a kódrészletet a link felépítéséhez:
import { url } from "@web/core/utils/urls";
const url = url("/web/image", {
model: resModel,
id: image_id,
field: imageField,
});
9. Váltás űrlap nézetre kattintáskor¶
Frissítse a renderelőt, hogy reagáljon egy képre kattintásra, és váltson űrlap nézetre. Használhatja az action service switchView függvényét.
Lásd még
10. Opcionális tooltip hozzáadása¶
Hasznos, ha van némi kiegészítő információ az egér fölé húzásakor.
Frissítse a kódot, hogy lehetővé tegye egy opcionális kiegészítő attribútum hozzáadását az arch-hoz:
<gallery image_field="some_field" tooltip_field="some_other_field"/>
Egér fölé húzásakor jelenítse meg a tooltip mező tartalmát. Működnie kell, ha a mező karakter mező, szám mező vagy many2one mező. Ha egy HTML elemhez szeretne tooltipet hozzáadni, az elemen belül a
data-tooltipattribútumba helyezheti a szöveget.Frissítse az ügyfél galéria nézet arch-ját, hogy az ügyfél legyen a tooltip mező.
11. Lapozás hozzáadása¶
Adjunk hozzá egy lapozót a vezérlőpanelhez, és kezeljük az összes lapozást, mint egy normál Odoo nézetben.
12. Nézetek érvényesítése¶
Eddig egy szép és hasznos nézetünk van. De a valóságban előfordulhat, hogy a felhasználók helytelenül kódolják a Galéria nézetük arch-ját: jelenleg csak egy strukturálatlan XML darab.
Adjunk hozzá némi érvényesítést! Az Odoo-ban az XML dokumentumok leírhatók egy RN fájllal (Relax NG fájl), majd érvényesíthetők.
Adjunk hozzá egy RNG fájlt, amely leírja a jelenlegi nyelvtant:
Egy kötelező attribútum:
image_field.Egy opcionális attribútum:
tooltip_field.
Adjunk hozzá némi kódot annak biztosítására, hogy minden nézetet érvényesítsenek ezzel az RNG fájllal.
Miközben ezzel foglalkozunk, győződjünk meg arról, hogy az
image_fieldés atooltip_fielda jelenlegi modell mezői.
Mivel egy RNG fájl érvényesítése nem triviális, itt van egy kódrészlet, amely segíthet:
# -*- coding: utf-8 -*-
import logging
import os
from lxml import etree
from odoo.loglevels import ustr
from odoo.tools import misc, view_validation
_logger = logging.getLogger(__name__)
_viewname_validator = None
@view_validation.validate('viewname')
def schema_viewname(arch, **kwargs):
""" Check the gallery view against its schema
:type arch: etree._Element
"""
global _viewname_validator
if _viewname_validator is None:
with misc.file_open(os.path.join('modulename', 'rng', 'viewname.rng')) as f:
_viewname_validator = etree.RelaxNG(etree.parse(f))
if _viewname_validator.validate(arch):
return True
for error in _viewname_validator.error_log:
_logger.error(ustr(error))
return False
13. Kép feltöltése¶
A galéria nézetünk nem teszi lehetővé a felhasználók számára a képek feltöltését. Valósítsuk meg ezt.
Adjon hozzá egy gombot minden képhez a
FileUploaderkomponens használatával.A
FileUploaderkomponens elfogadja azonUploadedtulajdonságot, amely akkor hívódik meg, amikor a felhasználó képet tölt fel. Győződjön meg róla, hogy awebSave-et hívja az orm szolgáltatásból az új kép feltöltéséhez.Lehet, hogy észrevette, hogy a kép feltöltődött, de a böngésző nem rendereli újra. Ennek oka, hogy a kép linkje nem változott, így a böngésző nem tölti újra őket. Tartalmazza a rekord
write_date-jét a kép URL-jébe.Győződjön meg róla, hogy a feltöltés gombra kattintás nem váltja ki a switchView-t.
14. Haladó tooltip sablon¶
Jelenleg csak egy tooltip mezőt tudunk megadni. De mi van akkor, ha szeretnénk egy konkrét sablont írni hozzá?
Example
Ez egy példa egy galéria arch nézetre, amelynek működnie kellene ezen gyakorlat után.
<record id="contacts_gallery_view" model="ir.ui.view">
<field name="name">awesome_gallery.orders.gallery</field>
<field name="model">res.partner</field>
<field name="arch" type="xml">
<gallery image_field="image_1920" tooltip_field="name">
<field name="email"/> <!-- Specify to the model that email should be fetched -->
<field name="name"/> <!-- Specify to the model that name should be fetched -->
<tooltip-template> <!-- Specify the owl template for the tooltip -->
<p class="m-0">name: <field name="name"/></p> <!-- field is compiled into a t-esc-->
<p class="m-0">e-mail: <field name="email"/></p>
</tooltip-template>
</gallery>
</field>
</record>
Cserélje le a
res.partnergaléria arch nézetet aawesome_gallery/views/views.xmlfájlban a fenti példában található arch-ra. Ne aggódjon, ha nem felel meg az rng validációnak.Módosítsa a galéria rng validátort, hogy elfogadja az új arch struktúrát.
Javaslat
Használhatja ezt az rng kódrészletet a tooltip-template címke validálásához
<rng:define name="tooltip-template"> <rng:element name="tooltip-template"> <rng:zeroOrMore> <rng:text/> <rng:ref name="any"/> </rng:zeroOrMore> </rng:element> </rng:define> <rng:define name="any"> <rng:element> <rng:anyName/> <rng:zeroOrMore> <rng:choice> <rng:attribute> <rng:anyName/> </rng:attribute> <rng:text/> <rng:ref name="any"/> </rng:choice> </rng:zeroOrMore> </rng:element> </rng:define>
Az arch elemzőnek elemeznie kell a mezőket és a tooltip sablont. Importálja a
visitXML-t a@web/core/utils/xmlfájlból, és használja a mezőnevek és a tooltip sablon elemzésére.Győződjön meg róla, hogy a modell meghívja a
webSearchRead-et az elemzett mezőnevek specifikációba való beillesztésével.The renderer (or any sub-component you created for it) should receive the parsed tooltip template. Manipulate this template to replace the
<field>element into a<t t-esc="x">element.Javaslat
A sablon egy
Elementobjektum, így úgy manipulálható, mint egy HTML elem.Regisztrálja a sablont az Owl-hoz az
@odoo/owlxmlfüggvényének köszönhetően.Használja a
@web/core/tooltip/tooltip_hookuseTooltiphook-ot az eszköztippek megjelenítéséhez. Ez a hook az Owl sablont és a sablon által igényelt változót veszi argumentumként.