Multiple level template inheritance in Jinja2?

41,825

Solution 1

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.

Solution 2

One of the best way to achieve multiple level of templating using jinja2 is to use 'include' let say you have 'base_layout.html' as your base template

<!DOCTYPE html>
<title>Base Layout</title>
<div>
  <h1>Base</h1>
  .... // write your code here
  {% block body %}{% endblock %}
</div>

and then you want to have 'child_layout.html' that extends 'base_layout.

{% include "base_layout.html" %}
  <div>
  ... // write your code here
  </div>
{% block body %}{% endblock %}

and now your page can just extends 'child_layout.html' and it will have both base_layout.html and child_layout.html

{% extends "child_layout.html" %}
{% block body %}
  ...// write your code here
{% endblock %}

Solution 3

Try this, this work for me thanks to @Ixm answer.

base.html

<html xmlns="http://www.w3.org/1999/xhtml">
    <body>
      {% block content %}{% endblock %}
    </body>
</html>

content.html

{% extends "base.html" %}
{% block content %}
<table>
  <tr>
  {% include "footer.html" %}
  </tr>
</table>
{% endblock %}

footer.html

{% block footer %} <td> test</td>{% endblock %}

and call with

env = Environment(loader=FileSystemLoader(os.path.join(path, "Layouts")))
template = env.get_template('content.html')
html = template.render()
print html

Solution 4

After struggling for a long time, I found {{super}} for multiple levels of inheritance in jinja2 templates.

The following is inspired from https://stackoverflow.com/a/31093830/1300775.

base.html

<html>
<body>
  {% block title %}
    Brand
  {% endblock %}
</body>

layer-1.html

  {% extends "base.html" %}
  {% block title %}
    {{ super() }} - Section
  {% endblock %}

layer-2.html

  {% extends "layer-1.html" %}
  {% block title %}
    {{ super() }} - Article
  {% endblock %}

Rendering template layer-2.html will output Brand - Section - Article (give or take a few spacing characters due to the indentation).

Solution 5

I recently faced the same issue. I wanted to inherit several child templates and it worked. To illustrate it I would like to show you a solution that worked for me:

I had a base.html file that has block content and extended by manage.html. and that manage.html has a block sub_manage which is extended by internet_market.html, so visually it looks like:

|- base.html (block content)
|--manage.html (extends base.html)
|---sub_manage.html (extends manage.html)

when I rendered it, everythink worked fine, which means that you can have several {% extends %} in one render. the only thing is that if you are using relative links to your css or js files then it might not work, rather it will render, but it won't find your css/js files. like:

<head>  
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<link rel="stylesheet" type="text/css" href="../static/css/bootstrap.min.css">
<script type="text/javascript" src="../static/js/bootstrap.min.js"></script>
<style type="text/css">
</head>

In that case you have to use dynamic links by using url_for. like:

<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<link rel="stylesheet" type="text/css" href="{{url_for("static", filename = "css/bootstrap.min.css")}}">
<script type="text/javascript" src="{{url_for("static", filename = "js/bootstrap.min.js")}}"></script>
<style type="text/css">
Share:
41,825
Rey
Author by

Rey

(your about me is currently blank)

Updated on July 09, 2022

Comments

  • Rey
    Rey almost 2 years

    I do html/css by trade, and I have been working on and off django projects as a template designer. I'm currently working on a site that uses Jinja2, which I have been using for about 2 weeks. I just found out through reading the documentation that Jinja2 doesn't support multiple level template inheritance, as in you can't do more than one

    {% extends "foo" %}
    

    per rendering. Now I'm pretty sure you can do this in Django, which is powerful because you can specify a base template, specify 3 or 4 templates based on that, and then build the meat of your pages using those base templates. Isn't the point of inheritance so you have more power to abstract so your only really messing with unique code?

    In any case I have no idea what to do here. I don't know if there is some way I can do it that will work as well as it could with the Django templates. I'm not exactly an expert at either Django or Jinja(2) but I can provide any information needed.

  • Chase Ries
    Chase Ries about 10 years
    I'm glad to see you sorted this out, I was wondering the same thing. I thought your original question was fairly clear. It can be so annoying to deal with the egos on StackOverflow -- someone above must have been very cranky the day you asked this question.
  • Max
    Max almost 10 years
    if I am not mistaken the problem of include is that it loads the html file even if there is no necessity for that file or even if the user did not make a request. But the advantage of extends is that the html file is rendered upon request. which will save time for loading the full page especially when there are lots of html files with huge codes
  • Rey
    Rey over 8 years
    this question still has a lot of life left in it, even 5 years later! Pretty funny.
  • JPB
    JPB over 7 years
    Why do you need the block on the footer if its being included?
  • Chockomonkey
    Chockomonkey about 5 years
    For what it's worth, i just deployed multi-level extending with jinja2 with perfect success, thanks to this post so i have a base.html, then extend it with further base_admin.html, base_client.html, base_form.html, etc. and then finally extend them with the actual pages, like accounts.html. No more code duplication!
  • S3DEV
    S3DEV almost 4 years
    @Rey - Let’s make that 11 years later! Nice one.
  • mLstudent33
    mLstudent33 over 3 years
    dunno why someone gave you -1 but this was what I was looking for to embed my app inside an existing dashboard layout
  • Dan King
    Dan King about 3 years
    @mLstudent33, if an answer is what you are looking for go ahead and up-vote it (click the triangle above the score).
  • ForyszeP
    ForyszeP almost 3 years
    Works perfectly! Fullfilled my requirements and saved a lot of time.