How to inherit a template with no ID in Odoo? - templates

I am trying to show the date a change was made in a task. To do this, I need to inherit the template of the widget "mail_thread". That template hasn't an id in its definition. This is it:
<?xml version="1.0" encoding="UTF-8"?>
<template>
<!--
mail.Widget template used to namespace the css -->
<t t-name="mail.Root">
<div class="oe_mail">
</div>
</t>
...
<span t-att-title="widget.date">
<t t-if="widget.timerelative" t-esc="widget.timerelative"/>
<t t-if="!widget.timerelative" t-raw="widget.display_date"/>
</span>
...
</template>
In my module, I need to replace the <span> tag in order to show the date.
So, how to inherit that template and replace the tag?

There are different inheritance mechanism for client side templates (web templates, defined inside a <templates> tag, "compiled" with javascript in the client when loading it) and server-side templates (usually views, must be included in the data list in the __openerp__.py file, 'compiled' when launching/upgrading the odoo server).
You extend web/widget templates templates using <t t-extend="template_name"> followed by one or more
<t t-jquery="jquery_selector" t-operation="operation"> which acts kinda like xpath, but client side and more 'powerful'.
You don't need ids, inheritance is based on the template name. (t-name directive)
Server-Side view inheritance
Client-Side 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-extend="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 itsel
No operation
if no t-operation is specified, the template body is interpreted as javascript code and executed with the context node as this

I also wanted to change the date show format in this xml file. So I copied the whole template for this default layout to my new module and only changed date in the span tag.
<?xml version="1.0" encoding="UTF-8"?>
<template>
<!-- default layout -->
<t t-name="mail.thread.message">
....
<span t-att-title="widget.date">
<!--<t t-if="widget.timerelative" t-esc="widget.timerelative"/>-->
<!--<t t-if="!widget.timerelative" t-raw="widget.display_date"/>-->
<t t-raw="widget.display_date"/>
</span>
....
</t>
</template>
need to declare this xml file in your __openerp__.py
It worked for me.

Related

xslt: Is there any way to reference the root node?

Is there any way to get access to the ROOT node from within another context?
The example above is just to show my intention. Getting access to ROOT_NODE without using '../../..' since changes in xml could break that type of selector.
XSLT
<div class="column">
<xsl:for-each select="languages/server/elem">
<!-- Context is ELEM node -->
<div>
<!-- How can I get access to the ROOT_NODE ?-->
<span class="text"><xsl:value-of select="ROOT_NODE/#title"/></span>
<!-- Print ELEM text -->
<span class="text"><xsl:value-of select="current()"/></span>
</div>
</xsl:for-each>
</div>
The expression "/" selects the document node at the root of the tree containing the context node. (All trees in 1.0 are rooted at document nodes.)
In XSLT 2.0, root() selects the root of the tree containing the context node whether or not the root is a document node.
To get the root of the principal source document even when the context node is a node in a different tree, bind a global variable
<xsl:variable name="principal-root" select="/"/>
which you can refer to anywhere as $principal-root.
Oh, and as Mads Hansen points out, if by "root node" you actually mean the outermost element node, as distinct from the document node, then you would typically use "/*".
The root node is the root of the XML tree, and is the space above the document element. Since an XML document could also have comments and processing instructions as top-level nodes, it gives you the ability to select them as well.
http://www.w3.org/TR/1999/REC-xpath-19991116/#location-paths
/ selects the document root (which is always the parent of the document element)
It sounds as if you want to reference the "root element", also known as the "document element", so that you can get the value of it's #title.
You can select that with the following XPath:
/*/#title

Nested template overwrite ui:default with ui:insert

Is there a rule on how to overwrite template definitions <ui:define> with <ui:insert>.
Template A:
<ui:composition xmlns:ui="http://java.sun.com/jsf/facelets">
template A content<br/>
<ui:insert name="content"/>
</ui:composition>
Template B:
<ui:composition template="/resources/templates/A.xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets">
<ui:define name="content">
template B content<br/>
<ui:insert name="content"/>
</ui:define>
</ui:composition>
Site 1:
<ui:composition template="/resources/templates/B.xhtml">
Site 1<br/>
<ui:define name="content">
site content<br/>
</ui:define>
</ui:composition>
Output:
Site 1
site content
Content for the <ui:define> is taken from Site 1, the content of the templates is not rendered.
Site 2:
<ui:composition template="/resources/templates/B.xhtml">
Site 2<br/>
</ui:composition>
Output:
Site 2
template B content
template A content
Content for the <ui:define> is taken from template B and template A, where strangely template B content is rendered before content of template A.
Is it possible to overwrite <ui:define> with a new <ui:insert> using same name?
Creating new names for the nested <ui:insert> is one possibility but its hard to keep track of the hierarchy and where insert's are used at all.
Unfortunately Facelets doesn't allow you to 'chain' insert/define.
In your first example (Site 1), there is single insert in Template A called "content". There are two definitions being considered; that of the direct template client (Template B) and that of the template client of Template B (Site 1). For this case, Facelets does not see that Template B has another insert. It just considers two competing definitions for "content", and the rule is that the top-most one wins, which is Site 1.
You did forgot to put the namespace on the template client though. The output you should be seeing is:
template A content
site content
Namely "template A content" is in the lowest template, outside the insert tag. It will be rendered directly. "site content" is in the top-most definition of "content".
In the second example (Site 2), there is no definition at all in the top-most template client. There is only one definition, and that's in Template B, so that one will be used. The output you should be seeing is:
template A content
template B content
You'll see "template A content" for the same reasons as in the first example, and "template B content" since it's the only definition. The nested second insert after that will be ignored.
Creating new names for the nested is one possibility but its hard to keep track of the hierarchy and where insert's are used at all.
It is indeed. Precisely for this reason I created a spec issue over a year ago for this at: https://github.com/eclipse-ee4j/faces-api/issues/1008
If this particular functionality is important to you please vote and/or leave a comment.

How can I add the filename of each used templates and includes in freemarker templates as HTML comments?

Is there a way to configure freemarker so that the Freemarker template engine automatically inserts the name of the current template as an HTML comment?
Example HTML output I would like to see:
<!-- template file: main.ftl -->
normal template code of the file main.ftl
<!-- template file: myinclude.ftl -->
This is the code from myinclude.ftl
I would like to use such functionality for debugging purposes only so that it is easier to find out which HTML fragments where rendered in which template.
Any hints?
You could write a TemplateLoader implementation that just delegates to another TemplateLoader (to the one that you are using when not in debug-mode), but captures the stream that it returns, and inserts the HTML comment after the <#ftl ...> directive. (But don't add line-break to the comment, or else it will offset the line number in error messages; use ${'\n'}<!-- ... -->${'\n'} instead.)

Xsl - How to select value from attribute whose name contains special character

My purpose is to get data from google place. I have the following snippet html:
<div class="rsw-pp rsw-pp-widget">
<div g:type="AverageStarRating"
g:secondaryurls="http://maps.google.com/?cid=12948004443906002997"
g:decorateusingsecondary="http://maps.google.com/?cid=12948004443906002997" g:groups="maps" g:rating_override="2.998000" class="rsw-stars">
</div>
</div>
I want to get value of g:rating_override. I tried with following xsl
<Rating>
<xsl:value-of
select="//div[#class='rsw-pp rsw-pp-widget']/div[#class='rsw-stars']/#g:rating_override" />
</Rating>
It said that 'System.Xml.Xsl.XsltException: Prefix 'g' is not defined'. Could you help me?
You need to define the "g" namespace. Typicaly this is done on the stylesheet element.
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:g=" ... "
version="1.0">
If you're using the Html Agility Pack embedded XSLT tools, you're facing two hard Html Agility Pack limits (at least with version 1.3.0.0):
Support for Namespaces is limited
The XPATH implementation does not support navigating to the attributes (only selection). This XPATH "//tag1/tag2/#myatt" does not work for example.
You can overcome these limits with C# code, but not easily with pure XPATH, hence not with XSLT.
In these case, it's often easier to convert the HTML to XML using the Html Agility Pack, and then use a regular XSLT on XML with the standard .NET classes, instead of XSLT on HTML with Html Agility Pack classes.

Finding Django template inheritance chain?

Given the path to a Django template, is there any easy way to find a list of the template's inheritance chain? For example, if mytemplate.html inherited from user-section-base.html, which inherited from global-base.html, it would be something like:
>>> print(get_template_chain('myapp/mytemplate.html'))
>>> ['/project/myapp/templates/myapp/mytemplate.html', '/project/myapp/templates/myapp/user-section-base.html', '/project/myapp/templates/myapp/global-base.html']
I'm trying to write a static site generator that automatically regenerates static pages from Django templates, and I need to detect when the underlying template changes since last generation. For a single flat template with no inheritance, this is trivial, but for a template that inherits from a parent, which also inherits from a parent, I need to track changes of those files as well.
However, I can't find any simple way to retrieve this, short of manually parsing the {% extends ... %} tags directly. What's the best way to do this?
the cleanest way is to hook to the template rendering engine, and try doing it there. That however, will require a deep dive into its code. Unless you are already familiar with the code base, I would say that going for parsing is the easiest and fastest option.
This is a very hacky way ;-) ...but if you are open to changing Django code, you can go to django/template/loader_tags.py and change the ExtendsNode.render return statement from
return compiled_parent._render(context)
to
return compiled_parent._render(context) + f'\n<!-- {compiled_parent.origin} -->'
and the rendered template will end with the full path of all your template-extends, e.g. for the file I'm working on right now:
</body>
</html>
<!-- c:\srv\lib\admindash\admindash\templates\admindash\html5.html -->
<!-- c:\srv\lib\admindash\admindash\templates\admindash\bootstrap3.html -->
<!-- c:\srv\lib\admindash\admindash\templates\admindash\site-admin.html -->
<!-- c:\srv\www\school\templates\site-admin.html -->
<!-- c:\srv\www\school\templates\page-admin.html -->
<!-- c:\srv\lib\dashboard\dashboard\templates\dashboard\tctr\home.html -->
<!-- c:\srv\lib\studentdb\studentdb\templates\studentdb\tctr\tctr-base.html -->
<!-- c:\srv\lib\studentdb\studentdb\templates\studentdb\tctr\candidates\candidate-base.html -->
Hooking into the template engine would be nice, but I'm not sure it can work out-of-the-box since .render(..) returns a string and thus loses all meta-data. Perhaps if you create your own {% extends ... %} tag..?