Jinja2 templates inheritance - python

With Jinja2, do all blocks need to be defined in the base template from which all other templates extend? For instance, given the following templates:
<-- ultra_base.j2 -->
<head>
</head>
<body>
{% block content %}{% endblock %}
{% block extra_js %} {% endblock %}
</body>
and
<-- child.j2 -->
{% extends ultra_base %}
{% block extra_js %}
<script src="somefile.js">
{% endblock %}
{% block page_js %} {% endblock %}
and
<-- grandchild.j2 -->
{% extends child %}
{% block content %}
<h2> Grandchild Content </h2>
{% endblock content %}
{% block page_js %}
<script src="grandchild.js"></script>
{% endblock page_js %}
The page_js block is never rendered. Is there some way to render it without changing ultra_base?

You could render page_js by putting the {% block page_js %} {% endblock %} inside the extra_js block in child.j2:
<-- child.j2 -->
{% extends ultra_base %}
{% block extra_js %}
<script src="somefile.js">
{% block page_js %}
{% endblock %}
{% endblock %}

The problem is that the page_js block in child.j2 is "in the middle of nowhere", it does not alter any block of the ulta_base.j2, so Jinja2 will not render anything from it. The solution is quite simple, you don't even need to define a new extra_js block, just use Jinja2's super() function:
ultra_base.j2 remains the same:
<!-- ultra_base.j2 -->
<head>
</head>
<body>
{% block content %}{% endblock %}
{% block extra_js %} {% endblock %}
</body>
the child.j2 template:
<!-- child.j2 -->
{% extends ultra_base %}
{% block extra_js %}
{{ super() }}
<script src="somefile.js"></script>
{% endblock %}
and the grandchildj2:
<!-- grandchild.j2 -->
{% extends child %}
{% block content %}
<h2> Grandchild Content </h2>
{% endblock content %}
{% block extra_js %}
{{ super() }}
<script src="grandchild.js"></script>
{% endblock extra_js %}
Jinja2 will take care of including block contents from the parent templates.

Related

Invalid block tag: 'endblock'. Did you forget to register or load this tag?

Given is my folder structure.
In 'home.html':
{% extends 'job_main/base.html' %}
{% block title %}Home{% endblock title %}
{% block content %}
<h1>Home Page</h1>
{% endblock content %}
In 'job_main/base.html':
<html>
<head>
<title>{% block title %}{% endblock title %} | Jobs Portal</title>
</head>
<body>
.
.
{% block content %} {% endblock content %}
</body>
You don't need to repeat a block name in the endblock. It should be just {% endblock %} instead of {% endblock title %}.

{% block content %}{% endblock %} doesn't load/work

{% extend 'base.html' %}
{% block content %}
<h2>NEW SEARCH</h2>
{% endblock %}
The template above doesn't work as it should.
You should use:
{% extends '<app_name>/base.html' %}
You forgot the s character when extending the template file.

Inherit template blocks from parent of parent in Django

I've 3 template files named **base.html**, **navbar.html** and **dashboard.html**.
base.html is the main parent file which has a **{% block content %}**.
Navbar has **{% block navtitle %}**.
Now What I want to do is, I want **navtitle** block in my 'dashboard.html' file.
Both navbar.html and dashboard.html extends **base.html**. I'm able to get **content** block from base.html file, but can't get navbar block.
Please guide me how can I do the same
Sample files below
base.html
{% block content %} {% endblock %}
navbar.html
{% extends 'base.html' %}
{% block navtitle %} {% endblock %}
dashboard.html
{% extends 'base.html' %}
{% block content %} Demo {% endblock %} # Able to print it
{% block navtitle %} Demo 2 {% endblock %} # Not able to print it
I also tried to extend navbar.html file in dashboard.html file but still no luck.
Using Inheritance (1/2)
base.html
{% block content %} {% endblock %}
{% block navtitle %} {% endblock %}
dashboard.html
{% extends 'base.html' %}
{% block content %} Demo {% endblock %}
{% block navtitle %} Demo 2 {% endblock %}
Using Inheritance (2/2)
useful when some templates will only inherit from base.html while others will inherit from navbar.html
base.html
{% block content %} {% endblock %}
{% block navtitle %} {% endblock %}
navbar.html
{% extends 'base.html' %}
{% block navtitle %} {% endblock %}
dashboard.html
{% extends 'navbar.html' %}
{% block content %} Demo {% endblock %}
{% block navtitle %} Demo 2 {% endblock %}
Using include
base.html
{% block content %} {% endblock %}
{% include "path/to/navbar.html" %}
navbar.html
<div>Some html</div>
dashboard.html
{% extends 'base.html' %}
{% block content %} Demo {% endblock %}
{% block navtitle %} Demo 2 {% endblock %}
Checkout django's templates documentation for include and inheritance

Global variables not defined in {% set %}

I have the following:
layout.html
{% if enableEntry or enableExit %}
{% from "cp.layout.html" import entry, exit %}
{% endif %}
<!DOCTYPE html>
<html lang="en">
<body>
{% if enableEntry %}{{ entry }}{% endif %}
{% if enableExit %}{{ exit }}{% endif %}
{% block body %}{% endblock %}
</body>
</html>
cp.layout.html
{% set entry %}
...
{% if offer.text_id == "mcd" %}
Mcdonald
{% elif offer.text_id == "bk" %}
Burger King
{% endif %}
...
{% endset %}
in my view:
def test():
.... (offer is defined here) ...
return render_template('layout.html', offer=offer)
I am getting an error that UndefinedError: 'offer' is undefined
Is there a way to pass variables that have global scope in the view to {% set %} blocs?
Seems like you never include your test.html under layout.html
I not sure is this help, this is my jinja 2 template design u can try
layout.html
{%- extends "test.html" %}
{# {% include "test.html" %} #}
{% block content %}
{{ super() }}
{%- endblock %}
test.html
{% block content %}
<div>
<h1>{{ offer }}</h1>
</div>
{% endblock %}
Let me know is this method work will give more explanation later

Override a block from an include via extend is blank?

So I have a base template, which includes a header:
base.html:
{% include "header.html" %}
header.html:
<ul>
<li><a>Link</a></li>
<li><a>Link</a></li>
<li><a>Link</a></li>
</ul>
{% block diskspace %}Test{% endblock %}
Then I would like to override the diskspace block from a template which extends the base, for instance:
album.html:
{% extends "base.html" %}
{% block diskspace %}
<p>You need more space!</p>
{% endblock %}
Unfortunately however diskspace only contains "Test" and is not overridden.
Is what I'm attempting possible, or do I need to go another route?
SOLUTION
Based on sergzach's answer below, here's what I ultimately implemented:
header.html:
<ul>
<li><a>Link</a></li>
<li><a>Link</a></li>
<li><a>Link</a></li>
</ul>
{% if show_diskspace %}
<p>You need more space!</p>
{% endif %}
base.html
{% block header %}
{% include "header.html" %}
{% endblock %}
album.html
{% extends "base.html" %}
{% block header %}
{% include "header.html" with show_diskspace="True" %}
{% endblock %}
header.html:
<ul>
<li><a>Link</a></li>
<li><a>Link</a></li>
<li><a>Link</a></li>
</ul>
{{diskspace}}
base.html
{% block header %}
{% include "header.html" with diskspace='Test'%}
{% endblock %}
album.html
{% extends "base.html" %}
{% block header %}
{% include "header.html" with diskspace='<p>You need more space!</p>'|safe %}
{% endblock %}

Categories