In some cases we need to customise part of a template, the template block mechanism is not granular enough. I noticed that in several cases there is some widget template, which contains a lot of macros. I don’t want to override the whole template, which implies all the widgets in the template. I need to override a couple of line in the macro.
Is there a way to import the core-template from the plugin-template?
An example:
from Indico-core you have a template A with the following content:
{% from 'B.html' import foo %}
{% macro A %}
do_this
do_that
{{ B() }}
{% endmacro %}
{% macro B %} .... {% endmacro %}
I want to change do_this, so in my template_override i would need something like:
{% from 'core:A' import B %}
{% macro A %}
do_something_else
do_that
{{ B() }}
{% endmacro %}
In this way if from another core-template someone uses {% from ‘A’ import A %} will be call the plugin-template A macro, which uses other parts of core-template A macro
Is it possible? is there some special convention to invoke explicitly a core-template?
Hi – an additional question to the discussion above:
I need to adjust/redefine the {% block title %} of the CORE template in our plugin: indico/modules/designer/templates/list.html
I have added another list.html template in our plugin’s template_overrides folder, trying several path locations within that, as well as several template extends ref e.g. {% extends ‘list.html’ %} – but this template is never picked up (always only the core list.html is executed).
What is missing? What should the file name, location, extends ref name, etc be for this template to be picked up and extend the core template?
Thanks – that combo was one of the many I have tried, but it does not work, the core list.html! What is the logic for knowing what the extending template filename and location should be, as well as how to refer to the extended template?
Of course that’s wrong - it sohuld be core/designer/list.html. But for now you can use the incorrect path and it should work. But once we fixed it (2.2.1) you will need to change it to core/designer/list.html.
The actual logic is to use /<core|(plugins/<pluginname>)>/<template_path> - but since the path is not 100% obvious in all cases (generally it’s <modulename>/<path inside that module's templates dir> except for indico/web/templates/ where there is no modulename prefix) it’s easier to just look at those log messages.
We’ll include it in 2.2.1, but since this is a minor and very limited issue (only happens for templates in the designer module) we’ll wait with releasing that version until there are more important fixes. Anyway, since you are doing development you will already have the fix if you run from the 2.2-maintenance branch.
Awesome, thanks! Updated to this and it works as expected.
While we’re in this specific template area – just noticed that the list.html template puts out invalid html, specifically referring to multiple html id=“template-list” attributes… maybe can also look into this? Thanks!
Oops! That shouldn’t happen. Do you want to send a PR against 2.2-maintenance to fix it? (in that case please do verify that the AJAX updates from data-update="#template-list" in _list.html still work correctly afterwards)
Sorry if I insist on the macro extension via child templates, but this is what a plugin should do in principle.
Is there a way to override a macro defined in a template from the core code-base without surrounding it with an {% if not macro %}?
core-foo.html
{% macro bar() %}Core - bar{% end %}
{% macro foo() %}Core - foo{% end %}
In case you are dealing with a template that only exports macros, don’t {% extend %} it but fully replace it, import the original macros (with the module-style import or aliased names), and then create your own macros that call the original ones (or not, depending on what you want to change).
Because it’s pretty ugly and overriding macros is not that common… You could possibly see if you can hack the Jinja core to automatically include this condition around all macro definitions. This would probably require subclassing the Jinja CodeGenerator (flask_pluginengine.templating.PluginCodeGenerator in our case), overriding visit_Macro to wrap it with custom code generating the conditional, and setting it as the code_generator_class of the jinja_environment on the Flask instance.