Komponenty strony (snippets)
Nowoczesne strony internetowe składa się z komponentów. W Odoo korzysta z nich edytor WebBuilder. Pozwala on na wstawianie komponentów w miejsca widoku, zaznaczone ramkami (div) klasy oe_structure (<div class="oestructure"/>
)
Poza szeregiem dostępnych komponentów mamy możliwość zbudowania własnych. Stwórzmy sobie prosty przykład (moduł demo_script). Poniżej wzorzec najprostszego kopononentu (pojawi się on po zainstalowaniu modułu na palecie po lewej - u samej góry):
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data>
<template id="demo_snippet.snippet1" name="Demo Snippet">
<section id="demo.sec">
<div class="row ">
<div class="col-sm-12">
nasz pierwszy snippet
</div>
</div>
</section>
</template>
<template id="demo_snippet.snippets" inherit_id="website.snippets"
name="Demo Snippets">
<xpath expr="//div[@id='snippet_structure']" position="before">
<div id="snippet_custom" class="o_panel">
<div class="o_panel_header">
<span class="fa-stack">
<i class="fa fa-mercury fa-stack-1x"></i>
</span> Demo Snippet
</div>
<div class="o_panel_body">
<t t-snippet="demo_snippet.snippet1"
t-thumbnail="/demo_snippet/static/src/img/snippet.png"
height="79" width="100"/>
</div>
</div>
</xpath>
</template>
</data>
</odoo>
Czy w takim komponencie można używać danych z modeli? Problem nie jest trywialny, ale też nie jest to zby skomplikowane. Ponieważ komponent może się pojawić na dowolnej stronie w dowolnym miejscu - trudno przewidzieć jakie dane będą dostępne. Z całą pewnością będą to jednak dane wykorzystywane do zbudowania szablonu (template) stron. Decyduje o tym moduł website. Zaimplementowano w nim rozszerzenie modelu ir_ui_view.py w którym przygotowywane są dane dla szablonu (funkcja _prepare_qcontext). Są to:
- website - aktualna strona (request.website)
- url_for - adres URL strony
- slug - część URL zawierająca opis podstrony (https://en.wikipedia.org/wiki/Semantic_URL#Slug)
- res_company - model zawierający dane firmy,
- user_id - dane z modelu res.users dla aktualnego użytkownika (browse),
- default_lang_code - kod domyślnego języka,
- languages - wszystkie dostępne języki
- translatable - czy strona może być tłumaczona,
- editable - czy strona może być edytowana
- menu_data - dane menu,
Najprościej jest odwołać się do powyższych danych. Na przykład zmieniając powyższy przykład następująco:
<template id="demo_snippet.snippet1" name="Demo Snippet">
<section id="demo.sec">
<div class="row ">
<div class="col-sm-12">
<h2>Zobacz kotku co mam w środku.</h2>
<div>website:
<div t-esc="website" />
</div><div>url_for:
<div t-esc="url_for" />
</div><div>slug:
<div t-esc="slug" />
</div><div>res_company.name:
<div t-esc="res_company.name"/>
</div>
</div>
</div>
</section>
</template>
A jeśli chcemy innych danych? Możemy je dostarczyć na kilka sposobów. Najprościej chyba jest rozszerzyć model res.company o własne pola obliczeniowe, które można wyświetlić w komponencie (tak jak powyżej name).
# -*- coding: utf-8 -*-
from odoo import models, fields, api
class ResCompany(models.Model):
_inherit = 'res.company'
dane_do_wyswietlenia = fields.Char('Dane ...', compute='_get_dane_do_wyswietlenia',
readonly=True)
# defniujemy tutaj, aby móc użyć w snippetach
@api.one
def _get_dane_do_wyswietlenia(self):
self.dane_do_wyswietlenia = 'jakieś dane';
Oczywiście w funkcji obliczającej wartość można pobierać dowolne dane - byle pamiętać o sudo().
Innym sposobem może być użytkowanie komponentów tylko na wybranych podstronach (nie zalecane), pobieranie danych z mechanizmem JavaScript Ajax, albo zmodyfikowanie modelu widoku podobnie jak zrobiono to w module website.
Parametry
Należy zwrócić uwagę na fakt, że użyty przy tworzeniu strony komponent zostaje zapamiętany z aktualnymi parametrami. Jeśli zawiera dane wygenerowane z bazy - to otwarcie strony nie powoduje ich uaktualnienia (chyba, że użyjemy w tym celu JavaScript). To samo dotyczy wariantów wyglądu, który możemy zmieniać w menu "Customize". Ustawienie tych parametrów wiąże się jedynie ze zmianą własności class w drzewie DOM strony. Szczerzej na ten temat: http://odoo-master.readthedocs.io/en/8.0/howtos/themes.html#advanced-customization