Modele i widoki
Podobnie jak strony internetowe, widoki ekranów zaplecza są przechowywane w plikach XML. Nie stosujemy tu jednak języka QWeb (poza definicją kontrolek/widgetów). Wzorce widoków (formularzy etc) - czyli definicje interfejsu użytkownika - są zapisywane w postaci danych wpisywanych do modelu "ir.ui.view"
. W niniejszym podręczniku można znaleźć wiele tego przykładów. Poniżej kilka zawarto dodatkowych informacji na które warto zwrócić uwagę.
Listy, formularze i drzewa - akcje okna
Definicja akcji otwierającej okno wygląda mniej więcej tak:
<record id="identygikator_akcji" model="ir.actions.act_window">
<field name="name">dowolny opis</field>
<field name="res_model">identyfikator.modelu</field>
<field name="view_id" ref="id_modułu.id_widoku"/>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
<field name="target">current</field>
</record>
Pole target może zawierać wartość:
- new - otwierane jest okienko modalne
- current - w aktualnym oknie
- inline - w polu edycji
- fullscreen - na cały ekran (znikają ikonki i menu poza otwartym oknem)
- main - w głównym onie (menu i ikonki pozostają)
Ponieważ widoki są związane z modelami, pole view_id
jest opcjonalne. Jeśli go nie podamy - zostanie wybrany widok standardowy - formularza.
Te trzy pola: view_id, view_type, view_mode
decydują o sposobie wyświetlenia zawartości modelu. Ze względów historycznych wartość view_mode = tree,form
oznacza zarówno listę jak i drzewo. Wybór następuje wówczas przez view_type
. Gdy ma on wartość form - mamy listę z przyciskami akcji, dodawania i wyszukiwania. Gdy wartość jest tree - mamy drzewo.
Zestawienie możliwych wartości:
view_id (rodzaj widoku) | view_type | view_mode | wynik |
---|---|---|---|
tree | tree | tree | drzewo |
tree | form | tree,form | lista |
tree | tree | tree,form | drzewo |
form | tree | tree | drzewo |
form | form | tree,form | formularz |
form | tree | tree,form | formularz |
Rekord akcji okna może zawierać dodatkowo pola kontekst (context - w nawiasach klamrowych {} ) i domenę (domain w nawiasach kwadratowych []).
Akcję okna można wywołać z menu lub przyciskiem formularza. Na przykład (div klasy oe_button_box
pojawia się u góry po prawej):
<div class="oe_button_box" name="button_box" position="inside">
<button class="oe_stat_button" type="action"
name="%(ident_akcji_okna)d" icon="fa-pencil-square-o" >
<div class="o_stat_info">
<span class="o_stat_text"> Wykonaj Akcję Okna </span>
</div>
</button>
</div>
Identyfikator ujęty w %( ... )d odnosi się do definicji w XML (a nie do modelu). Należy zwrócić uwagę na to, że przy wywolaniu funkcji modelu ustawiamy atrybut typ="object", a prz wywołaniu akcji (jak wyżej) type="action"!
Pola ukryte
W wielu formularzach są ukrywane dane, których użytkownik nie musi oglądać / zmieniać, ale muszą one być dostępne w zapytaniach (zamieniają się na <input type="hidden">). Definiuje się je przy pomocy własności invisible:
<field name="email" invisible="1"/>
Złożone formularze
W formularzach można zawrzeć tabelki z danymi (ale nie odwrotnie). Pokażemy to na prostym przykładzie dwóch modeli master-details. W modelu nadrzędnym mamy jedno pole - opis oraz odwołanie do tabeli parametrów (details). Jeśli chcemy mieć możliwość edycji tych parametrów w oknie modelu "master", musimy zdefiniować pole Many2one w modelu podrzędnym i One2many w modelu nadrzędnym:
class MasterModel(models.Model):
_name = 'demo.form.master'
_description = 'master'
opis = fields.Char('Opis')
details_ids = fields.One2many('demo.form.details', 'master_id', 'Parametry')
class DetailModel(models.Model):
_name = 'demo.form.details'
_description = 'details'
master_id = fields.Many2one('demo.form.master', 'Nadrzędny', ondelete='cascade',
index=True)
parametr = fields.Char('Parametry')
W formularzu możemy zdefiniować nie tylko listę parametrów, ale i okienko ich edycji (form) - zob. pole details_ids
poniżej:
<record id="demo_master_details.spis" model="ir.ui.view">
<field name="name">Spis</field>
<field name="model">demo.form.master</field>
<field name="arch" type="xml">
<tree string="lista">
<field name="opis" />
</tree>
</field>
</record>
<record id="demo_master_details.formularz" model="ir.ui.view">
<field name="name">Szczegóły</field>
<field name="model">demo.form.master</field>
<field name="arch" type="xml">
<form string="Szczegóły">
<group col="1">
<field name="opis" />
</group>
<notebook>
<page string="Parametry">
<field name="details_ids">
<tree string="Lista">
<field name="parametr" />
</tree>
<form string="Szczegóły">
<field name="parametr" />
</form>
</field>
</page>
</notebook>
</form>
</field>
</record>
Poprzez użycie kontekstu (context) możemy filtrować dane w tabelce detail: https://webkul.com/blog/odoo-domain-of-o2m-fields-onchange-of-parent-fields/
Dodatkowe możliwości zyskujemy dzięki użyciu kontrolek / widżetów (widgets). Na przykład w miejsce <field name="details_ids">
możemy wstawić <field name="details_ids" widget="one2many_list">
. Spis dostępnych w Odoo widżetów znajdziesz na stronie: https://www.cybrosys.com/blog/widgets-in-odoo.