How to repeat a "block" in a django template
Solution 1
I think that use of the context processor is in this case an overkill. You can easily do this:
#base.html
<html>
<head>
<title>{% block title %}My Cool Website{% endblock %}</title>
</head>
<body>
{% block content %}{% endblock %}
</body>
</html>
and then:
# blog.html
{% extends 'base.html' %}
{% block content %}
<h1>{% block title %}My Blog{% endblock %}</h1>
Lorem ipsum here...
{% endblock %}
and so on... Looks like DRY-compatible.
Solution 2
You probably don't actually want to use a block but rather to just use a variable:
# base.html
<html>
<head>
<title>{{ title|default:"My Cool Website" }}</title>
</head>
<body>
<h1>{{ title|default:"My Cool Website" }}</h1>
</body>
</html>
You then set the title through the context.
Solution 3
Here's a way I discovered when trying to do the same thing myself:
# base_helper.html
<html>
<head>
<title>{% block _title1 %}{% endblock %}</title>
</head>
<body>
<h1>{% block _title2 %}{% endblock %}</h1>
</body>
</html>
# base.html
{% extends "base_helper.html" %}
# Copy title into _title1 & _title2, using "My Cool Website" as a default.
{% block _title1 %}{% block _title2 %}{% block title %}My Cool Website{% endblock %}{% endblock %}{% endblock %}
Requires an extra file unfortunately, but doesn't require you to pass the title from the view.
Solution 4
you can use {% include subtemplate.html %}
more than once. it's not the same as blocks, but does the trick.
Solution 5
There are some discussion here: http://code.djangoproject.com/ticket/4529 Obviously django core team reject this ticket because they think this is not a common used scenario, however I disagree.
repeat block is simple and clean implementation for this: https://github.com/SmileyChris/django-repeatblock
template macros is another one, however the author mentioned it's not carefully tested: http://www.djangosnippets.org/snippets/363/
I used repeatblock.
David Arcos
Director of Engineering at Bling, teacher at ESADE, and organizer at PyBCN. I'm a technology generalist, coming from a strong technical background as a Python developer specialized in security, scalability and distributed systems. For the past 15 years, I've worked at several startups, building cloud platforms in sectors as diverse as video streaming, computer vision, in-flight entertainment, machine learning, cyber-security, healthcare, and fintech. I'm also teaching Cloud Computing at ESADE, organizer at the Python Barcelona Association, and a speaker at a number of technical conferences and webinars.
Updated on December 18, 2020Comments
-
David Arcos over 3 years
I want to use the same {% block %} twice in the same django template. I want this block to appear more than once in my base template:
# base.html <html> <head> <title>{% block title %}My Cool Website{% endblock %}</title> </head> <body> <h1>{% block title %}My Cool Website{% endblock %}</h1> </body> </html>
And then extend it:
# blog.html {% extends 'base.html' %} {% block title %}My Blog{% endblock %} # pictures.html {% extends 'base.html' %} {% block title %}My Pictures{% endblock %} # cats.html {% extends 'base.html' %} {% block title %}My Cats{% endblock %}
I will get an exception, as Django wants the block to appear only once:
TemplateSyntaxError at /
'block' tag with name 'title' appears more than once
A quick and dirty solution would be duplicating the block title into title1 and title2:
# blog.html {% extends 'base.html' %} {% block title1 %}My Blog{% endblock %} {% block title2 %}My Blog{% endblock %}
But this is a violation of the DRY principle. It would be very difficult as I have a lot of inheriting templates, and also because I don't wanna go to hell ;-)
Is there any trick or work-around to this problem? How can I repeat the same block in my template, without duplicating all the code?
-
Van Gale about 15 yearsThis has the same problem. The base template won't know which subtemplate to include.
-
thebiglife over 14 yearsI might try this tomorrow - I've been wondering how to save a bit of repetition in the templates and this seems like a good approach. thanks.
-
Roman Starkov over 14 yearsIn the end I settled for the {% macro %} solution, which doesn't require a new file, and overall lets me express exactly what I want to express.
-
lprsd over 14 yearsProbably Dry. But you wouldn't want to set the title within the view; but in the templates.
-
Guillaume Esquevin over 13 yearsTitles should be set from within the templates, not be provided by the context, you need to had a way to define this "title" variable, otherwise this is not a good solution.
-
Robert Lacroix almost 13 yearsI think that's the most elegant solution of all. Thanks Kieran and Van Gale!
-
SystemParadox over 12 yearsThis approach is excellent. I've split out my base.html into base.html and superbase.html, so this also works if you wanted to put a standard title markup (like an h1) in your shared templates. Pages can still override the content of the title block and it will update in both locations.
-
Tobu about 12 yearsThat's what the django admin templates do (for {{title}}), but defining the title at a remove is inconvenient.
-
acjay over 11 yearsThat's pretty slick, but it seems like it might be even better to render all of the nodes in the Set tag, otherwise they get rendered over and over again by Get. I can think of reasons that might be a good idea (rendering the same stored block inside of different blocks on a page), but I just thought I'd point it out.
-
Jonathan almost 10 yearsHowever
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.
-
natevw over 9 yearsThe original django-repeatblock repository seems to have been deleted. The best fork of that seems to be github.com/phretor/django-repeatblock; I also found github.com/ydm/django-sameas, which doesn't require a 'wontfix' Django patch.
-
Dennis Golomazov over 9 yearsThis doesn't allow to use the text more than twice, does it?
-
dqd about 9 yearsDenis Golomazov: No. In that case, it is better to use the macro plugin (see below).
-
François Constant about 9 yearsThis is a question about Django.
-
Mikael Lindlöf about 8 yearsCan also be applied the other way around: defining the
h1
content inside the block that defines thetitle
. Or a block that defines a part of thetitle
. -
Wtower over 7 years
-
TheKalpit about 6 yearsNeat! This approach also lets you define different content, if you need to, in each block.
-
benzkji almost 6 yearssimpel and efficient. unlike @dqd s answer, the blocks dont need to be nested, very useful for example for facebook og tags, that might have the same content as other head attributes. upvote!
-
Anupam almost 6 yearsGreat answer. This seems even DRYer than @dqd's answer since you have dont have to repeat the <h1> tag in each template that inherits base. This could be the accepted answer.
-
caram over 4 yearsExcellent! I've used this in more complex scenarios where I wanted to repeat the footer row of a table a the top. And the
<tr>
row was rather complex. -
Elendurwen over 2 yearsStill works in 2021!
-
Flimm over 2 yearsWhich snippet is this answer referring to?