diff --git a/content/developer/reference/frontend/qweb.rst b/content/developer/reference/frontend/qweb.rst index 7a5bfa7c7..e057422ee 100644 --- a/content/developer/reference/frontend/qweb.rst +++ b/content/developer/reference/frontend/qweb.rst @@ -491,6 +491,228 @@ Debugging is equivalent to ``importlib.import_module("pdb").set_trace()`` +Rendering cache: +---------------- + +``t-cache="key_cache"`` tags part of template to be cached at rendering time. +Every sub-directives will be call only during the first rendering. It means +that the sql queries excecuted during the rendering of those sub-directives +are also done only once. + +``t-nocache="documentation"`` tags part of template to be render every time. +The content can only use the root values. + +Why and when to use ``t-cache``? +'''''''''''''''''''''''''''''''' + +This directive is used to speed up the rendering, by caching parts of the final +document, which may save queries to the database. However, it should be used +sparingly, as ``t-cache`` will inevitably complicate templates (and their +understanding of ``t-set`` for example). + +However, in order to actually save database queries, it might be necessary to +render the template with values that are evaluated lazily. If those lazy +values are used in a cached part, they will not be evaluated if the part is +available in cache. + +The ``t-cache`` directive is useful for template parts using values that depend +on a limited amount of data. We recommend to analyze the rendering of the +template with the profiler (by activating the "**Add qweb directive context**" +option). Passing lazy values to the rendering in controllers allow you to +display the directives using these values and triggering the queries. + +A concern of using such a cache are making it available to different users +(different users should render the cached parts the same way). Another +potential issue is to invalidate its entries when necessary. For the latter, +the **key expression** should be chosen wisely. Using the ``write_date`` of a +recordset can make a cache key out-of-date without having to discard it +explicitly from the cache, for instance. + +One should also pay attention to the fact that the values in ``t-cache`` parts +are scoped. This implies that if there are ``t-set`` directives in this part of +the template, the rendering of what comes after it could be different than if +there was no ``t-cache`` directive. + +What if there is a ``t-cache`` inside a ``t-cache``? +'''''''''''''''''''''''''''''''''''''''''''''''''''' + +The parts are cached. Each containing only the string corresponding to its +rendering. Thus, the ``t-cache`` inside will probably be read less often, its +cache key will not necessarily be used. If this must be the case, then you may +need to add a ``t-nocache`` (on the same node or a parent). + +What is ``t-nocache`` used for? +''''''''''''''''''''''''''''''' + +If you want to cache part of a template with ``t-cache`` but a small piece must +remain dynamic and be evaluated at cache times. However, the part in +``t-nocache`` will not have access to the ``t-set`` value of the template. Only +the values ​​provided by the controller are accessible there. +For example, the menu is cached because it's the same all the time and takes +time to render (using the performance devtools with the qweb context lets you +investigate). However, in the menu, we want the ecommerce cart to be always up +to date. So there is a ``t-nocache`` to keep this part dynamic. + +The base of ``t-cache`` +''''''''''''''''''''''' + +The ``t-cache`` directive allows you to store the rendered result of a template. +The **key expression** (eg 42: ``t-cache="42"``) will be evaluated as a python +expression. This will be used to generate the **cache key**. So there can be +different **cache values** (cached render part) for the same template part. If +the **key expression** is a tuple or a list, it will be searched when generating +the **cache key**. If one or more recordsets are returned by the **key +expression**, then the model, ids and their corresponding write_date will be +used to generate the **cache key**. Special case: If the **key expression** +returns a Falsy value, then the content will not be cached. + +Example:: + +
+ + +
+ +In this case, there may be values ​​(string) in the cache corresponding to each +record already returned with a true condition, as well as for the false +condition. And if a module modifies the record, the write_date being modified, +the cached value is discarded. + +``t-cache`` and scoped values (``t-set``, ``t-foreach``...) +''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' + +Values in ``t-cache`` are scoped, this involves a change in behavior between +having or not having ``t-cache`` on one of the parent nodes. Don't forget to +take into account that Odoo uses a lot of templates, ``t-call`` and view +inheritance. Adding a ``t-cache`` can therefore modify the rendering of a +template that you do not see when editing. +(``t-foreach`` it's like a ``t-set`` for each iteration) + +Example:: + +
+ + + + + + + + + + + + + +
+ +Will render:: + +
+ 2 + 2 + + 2 + 1 +
+ + +The base of ``t-nocache`` +''''''''''''''''''''''''' + +The template part contained in a node with a ``t-nocache`` attribute is not +cached. This content is therefore **dynamic** and is rendered systematically. +However the available values are those provided by the controller (when +calling the ``_render`` method). + +Example:: + +
+
+ <t t-out="record.name"/> <i t-nocache="">(views: <t t-out="counter"/>)</i></titlle> + <content t-out="record.description"/> + </article> + </section> + +Will render (counter = 1):: + + <section> + <article> + <title>The record name <i>(views: 1)</i></titlle> + <content>Record description</content> + </article> + </section> + +Here the ``<i>`` tag that contains the container will always be rendered. While +the rest is as a single string in the cache. + +``t-nocache`` and scoped root values (``t-set``, ``t-foreach``...) +'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' + +The contents of the ``t-nocache`` tag can be used for documentation and to +explain why the directive is added. +The values are scoped into ``t-nocache``, these values are root values only +(values provided by the controller and/or when calling the ``_render`` method +of ``ir.qweb``). ``t-set`` can be done in the template part, but will not be +available elsewhere. + +Example:: + + <section> + <t t-set="counter" t-value="counter * 10"/> + <header t-nocache=""> + <t t-set="counter" t-value="counter + 5"/> + (views: <t t-out="counter"/>) + </header> + <article t-cache="record"> + <title><t t-out="record.name"/> <i t-nocache="">(views: <t t-out="counter"/>)</i></titlle> + <content t-out="record.description"/> + </article> + <footer>(views: <t t-out="counter"/>)</footer> + </section> + +Will render (counter = 1):: + + <section> + <header> + (views: 6) + </header> + <article> + <title>The record name <i>(views: 1)</i></titlle> + <content>Record description</content> + </article> + <footer>(views: 10)</footer> + </section> + +Here the ``<i>`` tag that contains the container will always be rendered. While +the rest is as a single string in the cache. The counter is not updated by the +``t-set`` out of the ``t-nocache`` + +``t-nocache-*`` add some primitive values in the cache +''''''''''''''''''''''''''''''''''''''''''''''''''''''' + +In order to be able to use values generated in the template, it is possible to +cache them. The directive is used as ``t-nocache-*="expr"`` where ``*`` is the +name of the chosen value and ``expr`` the python expression so the result will +be cached. The cached value must be primitive type. + +Example:: + + <section t-cache="records"> + <article t-foreach="records" t-as="record"> + <header> + <title t-field="record.get_method_title()"/> + </header> + <footer t-nocache="This part has a dynamic counter and must be rendered all the time." + t-nocache-cached_value="record.get_base_counter()"> + <span t-out="counter + cached_value"/> + </footer> + </article> + </section> + +The value ``cached_value`` is cached with the cached template part of +``t-cache="records"`` and add to the scoped root values each time. + Helpers ------- @@ -514,15 +736,20 @@ be returned from the controller (or further customized to suit). View-based '''''''''' -At a deeper level than the previous helper is the ``render`` method on -``ir.ui.view``: +At a deeper level than the previous helper is the ``_render`` method on +``ir.qweb`` (use the datable) and the public module method ``render`` +(don't use the database): -.. py:method:: render(cr, uid, id[, values][, engine='ir.qweb][, context]) +.. py:method:: _render(id[, values]) Renders a QWeb view/template by database id or :term:`external id`. - Templates are automatically loaded from ``ir.ui.view`` records. + Templates are automatically loaded from ``ir.qweb`` records. - Sets up a number of default values in the rendering context: + ``_prepare_environment`` method sets up a number of default values in + the rendering context. The ``http_routing`` and ``website`` addons, + also default values they need. + You can use ``minimal_qcontext=False`` option to avoid this default + value like the public method ``render``: ``request`` the current :class:`~odoo.http.Request` object, if any @@ -546,6 +773,11 @@ At a deeper level than the previous helper is the ``render`` method on used to expand or customize QWeb locally (by creating a "new" qweb based on ``ir.qweb`` with alterations) +.. py:method:: render(template_name, values, load, **options) + + :func:`load(ref)` + returns etree object, ref + .. _reference/qweb/javascript: .. todo:: the members below are no longer relevant, section to rewrite