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