Ten artykuł skupia się na przekazaniu wiedzy technicznej w zakresie dziedziczenia widoków QWeb templates. Jeśli nie wiesz czym są te widoki, gdzie je znaleźć i do czego służą - zapraszam do artykułu poświęconego edytowaniu szablonu strony z wykorzystaniem QWeb.

W tym artykule skupię się na pokazaniu kodu. Kod ten zmienia wygląd strony produktu. Celem było zmniejszenie obrazu i umieszczenie go w jednej linii z tytułem. Sprzedaję usługi a nie produkty. Zdjęcie poglądowe zajmowało zbyt dużo miejsca na ekranie. Oto jak wygląda strona przed i po podłączeniu szablonu rozszerzającego:

Strona produktu Odoo przed (duże zdjęcie) i po (małe zdjęcie w rzędzie z tytułem) dodaniu szablonu.

Obraz 1. Strona produktu Odoo przed (duże zdjęcie) i po (małe zdjęcie w rzędzie z tytułem) dodaniu szablonu.

Kod szablonu QWeb

Powyższe zmiany wizualne zostały uzyskane poprzez dodanie dwóch widoków dziedziczących. Poniżej znajdziesz kod szablonów.

Widok dziedziczący po website_sale.product

<data inherit_id="website_sale.product" active="True" name="Small image and title in top row" key="product_page_layout_small.x_custom_small_image_title_top">
    <xpath expr="//h1" position="before">
        <div class="row align-items-center mt-3">
        </div>
    </xpath>

    <xpath expr="//div[@id='product_details']/div[1]/div[1]/div[1]" position="inside">
        <xpath expr="//div[@id='product_detail_main']/div[1]" position="move"/>
    </xpath>

    <xpath expr="//div[@id='product_detail_main']/div" position="attributes">
        <attribute name="t-attf-class"/>
    </xpath>

    <xpath expr="//div[@id='product_details']/div[1]/div[1]/div[1]/div[1]" position="attributes">
        <attribute name="t-attf-class">col-lg-1 o_wsale_product_images position-relative</attribute>
    </xpath>

    <xpath expr="//div[@id='product_details']/div[1]/div[1]/div[1]" position="inside">
        <xpath expr="//h1" position="move"/>
    </xpath>

    <xpath expr="//h1" position="replace">
        <div class="col-lg-11">$0</div>
    </xpath>
</data>
<data inherit_id="website_sale.product" active="True" name="Small image and title in top row" key="product_page_layout_small.x_custom_small_image_title_top">
    <xpath expr="//h1" position="before">
        <div class="row align-items-center mt-3">
        </div>
    </xpath>

    <xpath expr="//div[@id='product_details']/div[1]/div[1]/div[1]" position="inside">
        <xpath expr="//div[@id='product_detail_main']/div[1]" position="move"/>
    </xpath>

    <xpath expr="//div[@id='product_detail_main']/div" position="attributes">
        <attribute name="t-attf-class"/>
    </xpath>

    <xpath expr="//div[@id='product_details']/div[1]/div[1]/div[1]/div[1]" position="attributes">
        <attribute name="t-attf-class">col-lg-1 o_wsale_product_images position-relative</attribute>
    </xpath>

    <xpath expr="//div[@id='product_details']/div[1]/div[1]/div[1]" position="inside">
        <xpath expr="//h1" position="move"/>
    </xpath>

    <xpath expr="//h1" position="replace">
        <div class="col-lg-11">$0</div>
    </xpath>
</data>
<data inherit_id="website_sale.shop_product_carousel" active="True" name="Small image title carousel adjustment">
    <xpath expr="//div[@id='o-carousel-product']" position="attributes">
        <attribute name="t-attf-class" remove="mb-3" separator=" "/>
    </xpath>
</data>
<data inherit_id="website_sale.shop_product_carousel" active="True" name="Small image title carousel adjustment">
    <xpath expr="//div[@id='o-carousel-product']" position="attributes">
        <attribute name="t-attf-class" remove="mb-3" separator=" "/>
    </xpath>
</data>

Analiza kodu szablonu

Pierwsza linia to definicja danych. Zawiera informacje po jakim widoku dziedziczy nasz widok, oraz kilka innych parametrów. inherit_id​ - id modelu po którym dziedziczy nasz widok. active​ - określa czy widok jest aktywny. Name​ - nazwa modelu.

Linie 2-5

Wyszukuję elementu h1 wyrażeniem xpath​. Ważne: jeśli istniałyby dwa elementy h1​, zwracany jest pierwszy.

Dodaję element <div>​ przed elementem h1​ (position="before"​).

Linie 7-9

Przenoszę (position="move"​) element //div[@id='product_detail_main']/div[1]​ do elementu //div[@id='product_details']/div[1]/div[1]/div[1]  (position="inside"​).

Linie 11-13

Usuwam z elementu //div[@id='product_detail_main']/div​ atrybut t-attf-class​. Ważne: próbowałem tutaj usuwać class​, ale w momencie dziedziczenia szablonu class​ jeszcze nie istnieje. t-attf-​ to dynamiczny atrybut QWeb który jest renderowany przez Odoo. class​ jest tworzona na podstawie tego atrybutu.

Linie 15-17

Nadpisuję atrybuty class​ elementu //div[@id='product_details']/div[1]/div[1]/div[1]/div[1]​ jako col-lg-1 o_wsale_product_images position-relative​.

Linie 19-21

Znów przesuwam element, tym razem h1​.

Linie 23-25

Opakowuję element h1​ w <div class="col-lg-11">$0</div>​. Ważne: używam position="replace"​ , co zastępuje element z xpath​ innym, z node'a wewnętrznego. Symbol $0 w Odoo QWeb reprezentuje oryginalną zawartość elementu, który nadpisujemy.

Snippet 2, Linie 2-4

Usuwam klasę mb-3​ w elemencie //div[@id='o-carousel-product'].

Podsumowanie

Szablony dziedziczone służą do manipulacji strukturą szablonu nadrzędnego. Możemy wykorzystać: