diff options
| author | Xavier Morel <xmo@openerp.com> | 2014-09-09 09:17:32 +0200 |
|---|---|---|
| committer | Xavier Morel <xmo@openerp.com> | 2014-10-06 19:13:43 +0200 |
| commit | 494dcbd0e3ee4370e3c4a5ac6635acf86f0d7481 (patch) | |
| tree | b0b84286216ee50d8f4480292435cf5afc64be22 /doc/reference | |
| parent | bed6b01c53b520591e6f693dbb5c25cc5b772bbc (diff) | |
[IMP] qweb doc, tests
* document qweb based (mostly) on JS version
* convert JS qweb tests to (mostly) language-independent XML so they can be
used for JS and Python implementations
* add some more tests (e.g. precedence between t-value and body in t-set)
* remove ``t-import``
* fix parity in foreach(dict) (and rename some variables to make array and
object versions more similar)
Diffstat (limited to 'doc/reference')
| -rw-r--r-- | doc/reference/http.rst | 2 | ||||
| -rw-r--r-- | doc/reference/javascript.rst | 3 | ||||
| -rw-r--r-- | doc/reference/qweb.rst | 450 |
3 files changed, 448 insertions, 7 deletions
diff --git a/doc/reference/http.rst b/doc/reference/http.rst index c179691c4cb..e36ddf9e713 100644 --- a/doc/reference/http.rst +++ b/doc/reference/http.rst @@ -59,7 +59,7 @@ and defining methods decorated with :func:`~openerp.http.route`:: return stuff() To *override* a controller, :ref:`inherit <python:tut-inheritance>` from its -class and override relevant methods:: +class and override relevant methods, re-exposing them if necessary:: class Extension(MyController): @route() diff --git a/doc/reference/javascript.rst b/doc/reference/javascript.rst index ae7b02c63a4..07f38b77fc1 100644 --- a/doc/reference/javascript.rst +++ b/doc/reference/javascript.rst @@ -5,6 +5,9 @@ Javascript Widgets ======= +.. qweb integration: ``template`` is an (optional) automatically rendered + template + RPC === diff --git a/doc/reference/qweb.rst b/doc/reference/qweb.rst index c993c0c3c22..8e8a213af44 100644 --- a/doc/reference/qweb.rst +++ b/doc/reference/qweb.rst @@ -1,26 +1,273 @@ +.. highlight:: xml + .. _reference/qweb: ==== QWeb ==== -Basics -====== +QWeb is the primary templating_ engine used by Odoo\ [#othertemplates]_. It +is an XML templating engine\ [#genshif]_ and used mostly to generate HTML_ +fragments and pages. + +Template directives are specified as XML attributes prefixed with ``t-``, +for instance ``t-if`` for :ref:`reference/qweb/conditionals`, with elements +and other attributes being rendered directly. + +To avoid element rendering, a placeholder element ``<t>`` is also available, +which executes its directive but doesn't generate any output in and of +itself:: + + <t t-if="condition"> + <p>Test</p> + </t> + +will result in:: + + <p>Test</p> + +if ``condition`` is true, but:: + + <div t-if="condition"> + <p>Test</p> + </div> + +will result in:: + + <div> + <p>Test</p> + </div> .. _reference/qweb/output: data output ------------ +=========== + +QWeb has a primary output directive which automatically HTML-escape its +content limiting XSS_ risks when displaying user-provided content: ``esc``. + +``esc`` takes an expression, evaluates it and prints the content:: + + <p><t t-esc="value"/></p> + +rendered with the value ``value`` set to ``42`` yields:: + + <p>42</p> + +There is one other output directive ``raw`` which behaves the same as +respectively ``esc`` but *does not HTML-escape its output*. It can be useful +to display separately constructed markup (e.g. from functions) or already +sanitized user-provided markup. .. _reference/qweb/conditionals: conditionals ------------- +============ + +QWeb has a conditional directive ``if``, which evaluates an expression given +as attribute value:: + + <div> + <t t-if="condition"> + <p>ok</p> + </t> + </div> + +The element is rendered if the condition is true:: + + <div> + <p>ok</p> + </div> + +but if the condition is false it is removed from the result:: + + <div> + </div> + +The conditional rendering applies to the bearer of the directive, which does +not have to be ``<t>``:: + + <div> + <p t-if="condition">ok</p> + </div> + +will give the same results as the previous example. .. _reference/qweb/loops: loops ------ +===== + +QWeb has an iteration directive ``foreach`` which take an expression returning +the collection to iterate on, and a second parameter ``t-as`` providing the +name to use for the "current item" of the iteration:: + + <t t-foreach="[1, 2, 3]" t-as="i"> + <p><t t-esc="i"/></p> + </t> + +will be rendered as:: + + <p>1</p> + <p>2</p> + <p>3</p> + +Like conditions, ``foreach`` applies to the element bearing the directive's +attribute, and + +:: + + <p t-foreach="[1, 2, 3]" t-as="i"> + <t t-esc="i"/> + </p> + +is equivalent to the previous example. + +``foreach`` can iterate on an array (the current item will be the current +value), a mapping (the current item will be the current key) or an integer +(equivalent to iterating on an array between 0 inclusive and the provided +integer exclusive). + +In addition to the name passed via ``t-as``, ``foreach`` provides a few other +variables for various data points (``$as`` is the name passed to ``t-as``): + +:samp:`{$as}_all` + the object being iterated over +:samp:`{$as}_value` + the current iteration value, identical to ``$as`` for lists and integers, + but for mappings it provides the value (where ``$as`` provides the key) +:samp:`{$as}_index` + the current iteration index (the first item of the iteration has index 0) +:samp:`{$as}_size` + the size of the collection if it is available +:samp:`{$as}_first` + whether the current item is the first of the iteration (equivalent to + :samp:`{$as}_index == 0`) +:samp:`{$as}_last` + whether the current item is the last of the iteration (equivalent to + :samp:`{$as}_index + 1 == {$as}_size`), requires the iteratee's size be + available +:samp:`{$as}_parity` + either ``"even"`` or ``"odd"``, the parity of the current iteration round +:samp:`{$as}_even` + a boolean flag indicating that the current iteration round is on an even + index +:samp:`{$as}_odd` + a boolean flag indicating that the current iteration round is on an odd + index + +.. _reference/qweb/attributes: + +attributes +========== + +QWeb can compute attributes on-the-fly and set the result of the computation +on the output node. This is done via the ``t-att`` (attribute) directive which +exists in 3 different forms: + +:samp:`t-att-{$name}` + an attribute called ``$name`` is created, the attribute value is evaluated + and the result is set as the attribute's value:: + + <div t-att-a="42"/> + + will be rendered as:: + + <div a="42"></div> +:samp:`t-attf-{$name}` + same as previous, but the parameter is a :term:`format string` + instead of just an expression, often useful to mix literal and non-literal + string (e.g. classes):: + + <t t-foreach="[1, 2, 3]" t-as="item"> + <li t-attf-class="row {{ item_parity }}"><t t-esc="item"/></li> + </t> + + will be rendered as:: + + <li class="row even">1</li> + <li class="row odd">2</li> + <li class="row even">3</li> +:samp:`t-att=mapping` + if the parameter is a mapping, each (key, value) pair generates a new + attribute and its value:: + + <div t-att="{'a': 1, 'b': 2}"/> + + will be rendered as:: + + <div a="1" b="2"></div> +:samp:`t-att=pair` + if the parameter is a pair (tuple or array of 2 element), the first + item of the pair is the name of the attribute and the second item is the + value:: + + <div t-att="['a', 'b']"/> + + will be rendered as:: + + <div a="b"></div> + +setting variables +================= + +QWeb allows creating variables from within the template, to memoize a +computation (to use it multiple times), give a piece of data a clearer name, +... + +This is done via the ``set`` directive, which takes the name of the variable +to create. The value to set can be provided in two ways: + +* a ``t-value`` attribute containing an expression, and the result of its + evaluation will be set:: + + <t t-set="foo" t-value="2 + 1"/> + <t t-esc="foo"/> + + will print ``3`` +* if there is no ``t-value`` attribute, the node's body is rendered and set + as the variable's value:: + + <t t-set="foo"> + <li>ok</li> + </t> + <t t-esc="foo"/> + + will generate ``<li>ok</li>`` (the content is escaped as we + used the ``esc`` directive) + + .. note:: using the result of this operation is a significant use-case for + the ``raw`` directive. + +calling sub-templates +===================== + +QWeb templates can be used for top-level rendering, but they can also be used +from within another template (to avoid duplication or give names to parts of +templates) using the ``t-call`` directive:: + + <t t-call="other-template"/> + +This calls the named template with the execution context of the parent, if +``other_template`` is defined as:: + + <p><t t-value="var"/></p> + +the call above will be rendered as ``<p/>`` (no content), but:: + + <t t-set="var" t-value="1"/> + <t t-call="other-template"/> + +will be rendered as ``<p>1</p>``. + +However this has the problem of being visible from outside the ``t-call``. +Alternatively, content set in the body of the ``call`` directive will be +evaluated *before* calling the sub-template, and can alter a local context:: + + <t t-call="other-template"> + <t t-set="var" t-value="1"/> + </t> + <!-- "var" does not exist here --> Python ====== @@ -33,5 +280,196 @@ Bundles Javascript ========== -loading +Exclusive directives +-------------------- + +The Javascript qweb implementation provides specific directives to handle +defining and overloading/altering templates: + +defining templates +'''''''''''''''''' + +The ``t-name`` directive can only be placed at the top-level of a template +file (direct children to the document root):: + + <templates> + <t t-name="template-name"> + <!-- template code --> + </t> + </templates> + +It takes no other parameter, but can be used with a ``<t>`` element or any +other. With a ``<t>`` element, the ``<t>`` should have a single child. + +The template name is an arbitrary string, although when multiple templates +are related (e.g. called sub-templates) it is customary to use dot-separated +names to indicate hierarchical relationships. + +template inheritance +'''''''''''''''''''' + +Template inheritance is used to alter existing templates in-place, e.g. to +add information to templates created by an other modules. + +Template inheritance is performed via the ``t-extend`` directive which takes +the name of the template to alter as parameter. + +The alteration is then performed with any number of ``t-jquery`` +sub-directives:: + + <t t-extends="base.template"> + <t t-jquery="ul" t-operation="append"> + <li>new element</li> + </t> + </t> + +The ``t-jquery`` directives takes a `CSS selector`_. This selector is used +on the extended template to select *context nodes* to which the specified +``t-operation`` is applied: + +``append`` + the node's body is appended at the end of the context node (after the + context node's last child) +``prepend`` + the node's body is prepended to the context node (inserted before the + context node's first child) +``before`` + the node's body is inserted right before the context node +``after`` + the node's body is inserted right after the context node +``inner`` + the node's body replaces the context node's children +``replace`` + the node's body is used to replace the context node itself +No operation + if no ``t-operation`` is specified, the template body is interpreted as + javascript code and executed with the context node as ``this`` + + .. warning:: while much more powerful than other operations, this mode is + also much harder to debug and maintain, it is recommended to + avoid it + +debugging +--------- + +The javascript QWeb implementation provides a few debugging hooks: + +``t-log`` + takes an expression parameter, evaluates the expression during rendering + and logs its result with ``console.log`` +``t-debug`` + triggers a debugger breakpoint during template rendering +``t-js`` + the node's body is javascript code executed during template rendering. + Takes a ``context`` parameter, which is the name under which the rendering + context will be available in the ``t-js``'s body + +Helpers ------- + +.. js:attribute:: openerp.qweb + + An instance of :js:class:`QWeb2.Engine` with all module-defined template + files loaded, and references to standard helper objects ``_`` + (underscore), ``_t`` (translation function) and JSON_. + + :js:func:`openerp.qweb.render <QWeb2.Engine.render>` can be used to + easily render basic module templates + +API +--- + +.. js:class:: QWeb2.Engine + + The QWeb "renderer", handles most of QWeb's logic (loading, + parsing, compiling and rendering templates). + + OpenERP Web instantiates one for the user, and sets it to + ``instance.web.qweb``. It also loads all the template files of the + various modules into that QWeb instance. + + A :js:class:`QWeb2.Engine` also serves as a "template namespace". + + .. js:function:: QWeb2.Engine.render(template[, context]) + + Renders a previously loaded template to a String, using + ``context`` (if provided) to find the variables accessed + during template rendering (e.g. strings to display). + + :param String template: the name of the template to render + :param Object context: the basic namespace to use for template + rendering + :returns: String + + The engine exposes an other method which may be useful in some + cases (e.g. if you need a separate template namespace with, in + OpenERP Web, Kanban views get their own :js:class:`QWeb2.Engine` + instance so their templates don't collide with more general + "module" templates): + + .. js:function:: QWeb2.Engine.add_template(templates) + + Loads a template file (a collection of templates) in the QWeb + instance. The templates can be specified as: + + An XML string + QWeb will attempt to parse it to an XML document then load + it. + + A URL + QWeb will attempt to download the URL content, then load + the resulting XML string. + + A ``Document`` or ``Node`` + QWeb will traverse the first level of the document (the + child nodes of the provided root) and load any named + template or template override. + + :type templates: String | Document | Node + + A :js:class:`QWeb2.Engine` also exposes various attributes for + behavior customization: + + .. js:attribute:: QWeb2.Engine.prefix + + Prefix used to recognize directives during parsing. A string. By + default, ``t``. + + .. js:attribute:: QWeb2.Engine.debug + + Boolean flag putting the engine in "debug mode". Normally, + QWeb intercepts any error raised during template execution. In + debug mode, it leaves all exceptions go through without + intercepting them. + + .. js:attribute:: QWeb2.Engine.jQuery + + The jQuery instance used during :ref:`template inheritance + <qweb-directives-inheritance>` processing. Defaults to + ``window.jQuery``. + + .. js:attribute:: QWeb2.Engine.preprocess_node + + A ``Function``. If present, called before compiling each DOM + node to template code. In OpenERP Web, this is used to + automatically translate text content and some attributes in + templates. Defaults to ``null``. + +.. [#genshif] it is similar in that to Genshi_, although it does not use (and + has no support for) `XML namespaces`_ + +.. [#othertemplates] although it uses a few others, either for historical + reasons or because they remain better fits for the + use case. Odoo 8.0 still depends on Jinja_ and Mako_. + +.. _templating: + http://en.wikipedia.org/wiki/Template_processor + +.. _Jinja: http://jinja.pocoo.org +.. _Mako: http://www.makotemplates.org +.. _Genshi: http://genshi.edgewall.org +.. _XML namespaces: http://en.wikipedia.org/wiki/XML_namespace +.. _HTML: http://en.wikipedia.org/wiki/HTML +.. _XSS: http://en.wikipedia.org/wiki/Cross-site_scripting +.. _JSON: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON +.. _CSS selector: http://api.jquery.com/category/selectors/ |
