Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

django: using blocks in included templates

I have some html structures that are reused in quite a few different places. It's different from a overall template so I can't extend it, it can also be used to contain complicated content so I don't think defining it as a template tag does a good job. Below is some pseudo code describing my desired outcome, when using template_level2.html you can easily put stuff into the reusable_pattern_template by calling the block inside it. If I do use this code, what you write in 'actual content' of template_level_2.html wouldn't show up. How should I deal with this?

base.html

<html> <head></head> <body> {% block content %}{% endblock %} </body> </html> 

template_level1.html

{% extends 'base.html' %} {% block content %}   Something here...   {% include 'reusable_pattern_template.html' %}   Something else here... {% endblock %} 

reusable_pattern_template.html

<div>   <div>     <div>       {% block local_content %}{% endblock %}     </div>    </div> </div> 

template_level2.html

{% extends 'template_level1.html' %} {% block local_content %}   Actual content here... {% endblock %} 

update: Sorry, the extends in template_level2.html has some misspelling, I've just corrected it.

It may not be very clear, but the code above is more of a pseudo code describing my desired outcome. In short,

  • I would like to include small pieces of reusable html patterns in my templates.
  • These patterns are like boxes, that you can put whole pieces of html content in them. So context variables may be a bit of too limited for my purpose
like image 557
Xun Yang Avatar asked Mar 09 '12 11:03

Xun Yang


People also ask

What is block in Django template?

In master templates the block tag is a placeholder that will be replaced by a block in a child template with the same name. In child templates the block tag is content that will replace the placeholder in the master template with the same name.

What does %% include?

{% include %} Processes a partial template. Any variables in the parent template will be available in the partial template. Variables set from the partial template using the set or assign tags will be available in the parent template.

What does {% endblock %} mean?

{% endblock %} </div> </body> </html> In this example, the {% block %} tags define four blocks that child templates can fill in. All the block tag does is tell the template engine that a child template may override those portions of the template.


2 Answers

Django does not process blocks in included files.

The include tag should be considered as an implementation of "render this subtemplate and include the HTML", not as "parse this subtemplate and include its contents as if it were part of the parent". This means that there is no shared state between included templates -- each include is a completely independent rendering process. (Django template tag documentation)

like image 84
Chris Pratt Avatar answered Oct 11 '22 14:10

Chris Pratt


I came across this problem and ended up with the following compromise, hoping someone else might find it useful. It relies on using with blocks in the child templates.

base.html wants to reuse a common nav.html include, but define some blocks where variables inside nav.html might be overriden by child templates.

<!-- base.html: --> <html>   [...]   <nav class="desktop">     {% block desktop_nav %}       {% include "includes/nav.html" %}     {% endblock %}   </nav>   [...]   <nav class="mobile">     {% block mobile_nav %}       {% include "includes/nav.html" %}     {% endblock %}   </nav>   [...] 

The include template depends on a variable called selected, which base.html does not define, by default:

<!--includes/nav.html:--> <a href="/about/" class="{% if selected == 'about' %}selected{% endif %}">About</a> <a href="/people/" class="{% if selected == 'people' %}selected{% endif %}">People</a> <a href="/contact/" class="{% if selected == 'contact' %}selected{% endif %}">Contact</a> 

But child pages can override that value as follows:

<!--about.html:--> {% extends "base.html" %} {% block desktop_nav %}{% with selected='about' %}{{ block.super }}{% endwith %}{% endblock %} {% block mobile_nav %}{% with selected='about' %}{{ block.super }}{% endwith %}{% endblock %} 

so, not perfect, I still have to have two separate blocks and use those with blocks twice, but it does allow me to override variables in include blocks from the parent template.

like image 33
hwjp Avatar answered Oct 11 '22 13:10

hwjp