Multiple Level Template Inheritance in Jinja2

Multiple level template inheritance in Jinja2?

The way the documentation worded it, it seemed like it didn't support inheritance (n) levels deep.

Unlike Python Jinja does not support
multiple inheritance. So you can only
have one extends tag called per
rendering.

I didn't know it was just a rule saying 1 extends per template.... I now know, with some help from the jinja irc channel.

Jinja2 Multi-level template inheritance issue

I understand your issue: you've got template A, template B (extends template A), and template C (extends template B). There's a block defined in template A, but it's not showing up in the page that uses template C, unless you define that block in template B. If you do that, then the block in question shows up.

First: you are correct in your understanding that this is not how the Jinja template hierarchy is supposed to work. Second, I did not encounter your issue (found a different one, though), and I have constructed a proof to demonstrate this. Here's what I did (again, using Python 3 and Django 1.11):

$ python startproject myapp

In the myapp/myapp/settings.py file, I updated the template engine:

TEMPLATES = [
{
'BACKEND': 'django.template.backends.jinja2.Jinja2',
'DIRS': [
os.path.join(BASE_DIR, 'myapp/templates') # hack / should add `myapp` to INSTALLED_APPS instead
],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]

In myapp/myapp/urls.py, I created a dummy view function & route:

from django.conf.urls import url
from django.shortcuts import render_to_response

def home(request):
return render_to_response('dashboard.html')

urlpatterns = [
url(r'^$', home),
]

And finally, I established those templates, but I removed the call to import your macros, along with all instances of static().

Here is the myapp/myapp/templates/skeleton.html file:

<!doctype html>
<html lang="en">
<head>
{% block head_content %}
<meta charset="utf-8">
<title> {% if page_title %} {{ page_title }} | {% endif %} Bhargavi Books & Stationery </title>
{% endblock head_content %}
</head>

<body>
<div id="navigation">
{% block navigation %}
<div class="ui three item menu">
<a class="active item">Home</a>
<a class="item">New Bill</a>
<a class="item">View Bills</a>
</div>
{% endblock navigation %}
</div>

<div id="frame">
{% block frame_content %}
<p> Body content goes here. Body for {{ content_name }}</p>
{% endblock frame_content %}
</div>

<div id="app">
{% block app_content %}
<p> APP content goes here. Body for {{ content_name }}</p>
{% endblock app_content %}
</div>

{% block scripts %}
{% endblock scripts %}
</body>
</html>

Here is the myapp/myapp/base.html file:

{% extends "skeleton.html" %}

{% block frame_content %}
Frame Content
{% endblock frame_content %}

{% block scripts %}
{{ super() }}
{% endblock scripts %}

And here is the myapp/myapp/templates/dashboard.html file:

{% extends "base.html" %}

<div>
{% block body_content %}
Body 3
{% endblock body_content %}
</div>

<div>
{% block app_content %}
DASHBOARD
{% endblock app_content %}
</div>

And here is the output, after viewing that page in my browser:

<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title> Bhargavi Books & Stationery </title>
</head>

<body>
<div id="navigation">
<div class="ui three item menu">
<a class="active item">Home</a>
<a class="item">New Bill</a>
<a class="item">View Bills</a>
</div>
</div>

<div id="frame">
Frame Content
</div>

<div id="app">
DASHBOARD
</div>
</body>
</html>

Since this all works as expected*, my conclusion is that you might have a problem with the base.html template file. Perhaps it's failing to import your macros, and subsequently not behaving correctly? I notice a trailing comma in there, and I'm not sure if that could be problematic or not. I would suggest using the above code as a starting point, and then slowly add back in the parts that I stripped out, and perhaps the problem will become visible/understandable.

*One thing I found odd, that I don't understand: the body_content block is completely missing from my output, unless I define that block in the skeleton.html template. It doesn't work if I define it in the base.html template, which seems wrong to me, because then we're not really extending that second template (base.html)... so there does seem to be something weird there... but I was not able to encounter the original issue you described, so maybe this will be helpful in that particular regards, at least.

jinja2 template inheritance sample does not work

Jinja2 follows inheritance from your TEMPLATE_DIRS settings. I'm assuming that you have an incorrect path. Try:

{% extends "myapp/base.html" %}

concat multiple block in jinja2?

I assume that by multiple children, you mean that there are templates inheriting from templates inheriting from templates ... inheriting from the base template. If that's the case, you need to define the same javascript block in each template and call super() in all of the children, in addition to adding more JavaScript. Calling super() prints the output of the parent's javascript block, and so on up the chain of inheritance. Along the way, each block may add code of its own.

So you could have something like this in each template:

{% block javascript %}
{{ super() }}

function foo(x, y) {
return x + y;
}
{% endblock %}

How do I remove duplicated template inheritance in Mobile and Desktop with Jinja2?

You need to remove duplicate code below code

<div class="d-none d-md-block">
{{Foo}}
</div>

And instead to go to add duplicate blocks for mobile and web, you just need to add one block of code for mobile and desktop and add/update classes on its parent container based on the screen sizes.

we have javascript object window.navigator.platform which gives you the platform you are using. Based on that platform and window.innerWidth you can add/update classes of your graph container.

Correct syntax for multiple if not + OR in Jinja2 if statement

The in logical operator should help you in this case. Try this sample:

{%- if not asnitem.asn in [45102, 24429, 132203] %}

in operator here checks presence of the left-hand value (asnitem.asn) in the right-hand list ([45102, 24429, 132203]). And not inverts the result of the check.



Related Topics



Leave a reply



Submit