[IMP] qweb: document 't-cache' and 't-nocache' directives
related with: https://github.com/odoo/odoo/pull/88276 closes odoo/documentation#2056 Related: odoo/enterprise#27582 Related: odoo/upgrade#3451 Related: odoo/odoo#88276 Signed-off-by: Antoine Vandevenne (anv) <anv@odoo.com>
This commit is contained in:
parent
f477cf5f1c
commit
7c4656f0c4
@ -491,6 +491,228 @@ Debugging
|
|||||||
|
|
||||||
is equivalent to ``importlib.import_module("pdb").set_trace()``
|
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::
|
||||||
|
|
||||||
|
<div t-cache="record,bool(condition)">
|
||||||
|
<span t-if="condition" t-field="record.partner_id.name">
|
||||||
|
<span t-else="" t-field="record.partner_id" t-options-widget="contact">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
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::
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<t t-set="a" t-value="1"/>
|
||||||
|
<inside>
|
||||||
|
<t t-set="a" t-value="2"/>
|
||||||
|
<t t-out="a"/>
|
||||||
|
</inside>
|
||||||
|
<outside t-out="a"/>
|
||||||
|
|
||||||
|
<t t-set="b" t-value="1"/>
|
||||||
|
<inside t-cache="True">
|
||||||
|
<t t-set="b" t-value="2"/>
|
||||||
|
<t t-out="b"/>
|
||||||
|
</inside>
|
||||||
|
<outside t-out="b"/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
Will render::
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<inside>2</inside>
|
||||||
|
<outside>2</inside>
|
||||||
|
|
||||||
|
<inside>2</inside>
|
||||||
|
<outside>1</inside>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
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::
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<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>
|
||||||
|
</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
|
Helpers
|
||||||
-------
|
-------
|
||||||
|
|
||||||
@ -514,15 +736,20 @@ be returned from the controller (or further customized to suit).
|
|||||||
View-based
|
View-based
|
||||||
''''''''''
|
''''''''''
|
||||||
|
|
||||||
At a deeper level than the previous helper is the ``render`` method on
|
At a deeper level than the previous helper is the ``_render`` method on
|
||||||
``ir.ui.view``:
|
``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`.
|
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``
|
``request``
|
||||||
the current :class:`~odoo.http.Request` object, if any
|
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
|
used to expand or customize QWeb locally (by creating
|
||||||
a "new" qweb based on ``ir.qweb`` with alterations)
|
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:
|
.. _reference/qweb/javascript:
|
||||||
|
|
||||||
.. todo:: the members below are no longer relevant, section to rewrite
|
.. todo:: the members below are no longer relevant, section to rewrite
|
||||||
|
Loading…
Reference in New Issue
Block a user