I'm currently writing a quick python script to adapt all my old templates to a new base-template.
To do this I need to move the code inside the {% block body %} somewhere else.
I already got this one to match all my {% load smth %}
r"\{% load [^\{%]+? %\}"
What I want to match is the code between {% block body %} and {% endblock %}
Example:
{% block body %}
<div class="row">
<div class="span12">
[...]
</div>
</div>
{% endblock %}
unfortunately, there is no way to use regexp here, unless you use the notation {% endblock body %}, or you don't use nested blocks. Here is an example why it will fail:
{% block body %}
<div class="row">
<div class="span12">
{% block foo %}
[...]
{% endblock %}
</div>
</div>
{% endblock %}
regex will catch nested {% endblock %} as end of the body block
Leaving the obvious problem of nested blocks aside, this would be the regex to match all not-nested blocks:
\{% block [^\{%]+? %\}[\s\S]*\{% endblock %\}
Related
I am developing a dictionary application using Django. One of the main themes of the app is displaying feeds of definitions.
Specifically, I have:
an "index" feed where new definitions are listed,
a "headword" feed where definitions of a particular headword are listed,
and a "tag" feed where definitions tagged with a particular tag are listed.
index.html:
{% block body %}
<h1>Definitions</h1>
<ul>
{% for definition in definitions %}
// definition HTML
{% endfor %}
</ul>
{% endblock %}
headword.html:
{% block body %}
<h1>{{ headword }}</h1>
<ul>
{% for definition in headword.definitions_headword.all %}
// definition HTML
{% endfor %}
</ul>
tag.html:
{% block body %}
<h1>{{ tag }}</h1>
<ul>
{% for definition in tag.definitions_tag.all %}
// definition HTML
{% endfor %}
</ul>
Clearly, I need a base feed.html template that these three files can share. For the h1 tag no problem. However, I am having problems with the for loop iterable variables.
I tried nesting a {% block iterable %}{% endblock %} in the for loop of feed.html as in {% for definition in {% block iterable %}{% endblock %} %} and then plugging definitions, headword.definitions_headword.all, and tag.definitions_tag.all in {% block iterable %}, but Django does not seem to support that.
I could probably pass to all three templates a "definitions" context variable and use that as the iterable in all three for loops, but is there a way to do it without touching Python code?
Your explanation was a bit fuzzy to me at the end there, but going just based off your first sentence of "Clearly, I need a base feed.html template that these three files can share."
I think {% include %} may be what you are looking for.
https://docs.djangoproject.com/en/3.0/ref/templates/builtins/#include
Create your base template of "feed.html" which includes generic variables. Generic variables below are "header_name" and "definitions".
<h1>{{ header_name }}</h1>
<ul>
{% for definition in definitions %}
// definition HTML
{% endfor %}
</ul>
In your parent templates (index, headword, tag), use the "include" tag. Pass in your parent template variables into the child template. Examples below:
headword.html
{% block body %}
{% include 'pathname/feed.html' with header_name=headword definitions=headword.definitions_headword.all %}
{% endblock %}
tag.html
{% block body %}
{% include 'pathname/feed.html' with header_name=tag definitions=tag.definitions_tag.all %}
{% endblock %}
I'm calling a template in extended template.
I can't not find 'how to extended template call the other template in jinja2?'
base.html
<div class="main-container">
{% block content %}
{% endblock %}
</div>
child.html
{% extends "base.html" %}
{% block content %}
<div class="child">
<button class="modal"/>
{% modal content %}
{% endblock %}
</div>
{% endblock %}
modal content.html
<div class="modal-content">
...some code
</div>
I want call modal content in child.html.
If you're meaning you want to add the content.html into the child.html page, use include
Within child.html:
{% include 'content.html' %}
I made a template tag with the objective of simplifying the inclusion of Angular.
The tag responsible for setting some variables in the context is the following:
#register.simple_tag(takes_context=True)
def ng_controller(context, controller_name, file_name):
context['angular_import'] = True
context['angular_controller_file'] = file_name
return 'ng-controller="{}"'.format(controller_name)
the root template has this block in place of the javascript imports
{% block container_content %}{% endblock %}
{% block angular_inclusion %}{% endblock %}
the template that inherits the root template is this
{% extends 'root.html' %}
{% block container_content %}
<div class="row">
<div class="col-sm-12">
<div class="well" {% ng_controller 'CreateEdictController' 'js/controllers/create-edict-controller.js' %}>
{{ angular_controller_file }}
</div>
</div>
</div>
{% endblock %}
{% block angular_inclusion %}
{{ angular_controller_file }}
{% endblock %}
I can successfully access {{ angular_controller_file }} in the first block, but not in the second block. How can I ensure the context manipulation affects the second block also?
Variable scope in context
Any variable set in the context will only be available in the same
block of the template in which it was assigned. This behavior is
intentional; it provides a scope for variables so that they don’t
conflict with context in other blocks.
So the tag call in the first block container_content:
<div class="well" {% ng_controller 'CreateEdictController' 'js/controllers/create-edict-controller.js' %}>
Is ignored and missing in the second block, angular_inclusion
I am using jinja2 as a template language in my project. Here is simplified templates structure:
base.html:
{% block content %}{% endblock %}
{% block sidebar %}{% endblock %}
content.html:
{% extend 'base.html' %}
{% block content %}
<div class="content">
Content
{% block sidebar %}
<div class="sidebar">Sidebar</div>
{% sidebar %}
</div>
{% endblock %}
And the result of content.html render:
<div class="content">
Content
<div class="sidebar">Sidebar</div>
</div>
<div class="sidebar">Sidebar</div>
As you may see, sidebar is present twice at rendered content.html.
Question:
Is there a way to avoid appearance of the sidebar in content, leaving {% block sidebar %} inside {% block content %} ?
I think your content.html template is invalid - you're clearly positioning sidebar related content inside the content block, so it will allways appear there. Also, your base.html seems invalid as well, it should look more like:
{% block content %}{% endblock %}
{% block sidebar %}{% endblock %}
So if I were to do something like {% block content %}
{{variable}}
{% endblock %}
in my HTML, and variable is equal to "Test <br /> test2" how come the prints out and does not make a new line? is there a way to fix this?
Jinja2 automatically escapes special characters for you. Probably simplest way is to use safe filter:
{{ variable|safe }}
If your output is escaped and you see literal <br /> text in your browser, switch off autoescaping for the variable:
{% block content %}{% autoescape false %} {{variable}} {% endautoescape %}{% endblock %}
or tell Jinja2 that the variable is safe for interpolation:
{% block content %} {{variable|safe}} {% endblock %}