80👍
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.
83👍
Use the Django template macros plugin:
https://gist.github.com/1715202 (django >= 1.4)
or
http://www.djangosnippets.org/snippets/363/ (django < 1.4)
django >= 1.4
# base.html
{% kwacro title %}
{% block title %}My Cool Website{% endblock %}
{% endkwacro %}
<html>
<head>
<title>{% usekwacro title %}</title>
</head>
<body>
<h1>{% usekwacro title %}</h1>
</body>
</html>
and
# blog.html
{% extends 'base.html' %}
{% block title %}My Blog{% endblock %}
django < 1.4
# base.html
{% macro title %}
{% block title %}My Cool Website{% endblock %}
{% endmacro %}
<html>
<head>
<title>{% usemacro title %}</title>
</head>
<body>
<h1>{% usemacro title %}</h1>
</body>
</html>
and
# blog.html
{% extends 'base.html' %}
{% block title %}My Blog{% endblock %}
- [Django]-Printing Objects in Django
- [Django]-Django 2.0 – Not a valid view function or pattern name (Customizing Auth views)
- [Django]-Django: How to format a DateField's date representation?
20👍
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.
- [Django]-How can I disable logging while running unit tests in Python Django?
- [Django]-Convert Django Model object to dict with all of the fields intact
- [Django]-Get model's fields in Django
17👍
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.
- [Django]-How can I call a custom Django manage.py command directly from a test driver?
- [Django]-ValueError: The field admin.LogEntry.user was declared with a lazy reference
- [Django]-A field with precision 10, scale 2 must round to an absolute value less than 10^8
13👍
you can use {% include subtemplate.html %}
more than once. it’s not the same as blocks, but does the trick.
- [Django]-Best practices for adding .gitignore file for Python projects?
- [Django]-Django: manage.py does not print stack trace for errors
- [Django]-Unique fields that allow nulls in Django
6👍
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.
- [Django]-Django – No module named _sqlite3
- [Django]-Switching to PostgreSQL fails loading datadump
- [Django]-Data Mining in a Django/Postgres application
5👍
As an update for anyone coming across this, I’ve taken the snippet mentioned above and turned it into a template tag library, django-macros, makes the macros more powerful and also implements a repeated block pattern explicitly: django-macros.
- [Django]-TypeError: data.forEach is not a function
- [Django]-How to serve media files on Django production environment?
- [Django]-Macros in django templates
5👍
Here is a lightweight solution similar to the above do_set
and do_get
template tag answer. Django allows you to pass the entire template context into a tag which can allow you to define a global variable.
base.html:
<!DOCTYPE html>
<html lang="en">
<head>
{% block head %}
<title>{{ title }}</title>
{% endblock %}
</head>
<body>
<h1>{{ title }}</h1>
</body>
</html>
page.html:
{% extends "base.html" %}
{% block head %}
{% define 'title' 'Homepage | title' %}
{{ block.super }}
{% endblock %}
custom tag (got the idea here: https://stackoverflow.com/a/33564990/2747924):
@register.simple_tag(takes_context=True)
def define(context, key, value):
context.dicts[0][key] = value
return ''
Also don’t forget to {% load %}
your custom tags or add them to the template options builtins list so you don’t have to load them in every template. The only limitation to this approach is the {% define %}
has to be called from within a block tag because child templates only render block tags that match the parent tags. Not sure if there is a way around that. Also make sure the define
call comes before you try to use it obviously.
- [Django]-Django – Rotating File Handler stuck when file is equal to maxBytes
- [Django]-What does "'tests' module incorrectly imported" mean?
- [Django]-How to do SELECT COUNT(*) GROUP BY and ORDER BY in Django?
4👍
I use this answer to keep things dry.
{% extends "base.html" %}
{% with "Entry Title" as title %}
{% block title %}{{ title }}{% endblock %}
{% block h1 %}{{ title }}{% endblock %}
{% endwith %}
- [Django]-Extend base.html problem
- [Django]-Django-taggit – how do I display the tags related to each record
- [Django]-Django: How to check if the user left all fields blank (or to initial values)?
3👍
Building on Van Gale’s suggestion, you could create get and set tags by adding the following to your templatetags.py file:
register = template.Library()
Stateful = {}
def do_set(parser, token):
_, key = token.split_contents()
nodelist = parser.parse(('endset',))
parser.delete_first_token() # from the example -- why?
return SetStatefulNode(key,nodelist)
class SetStatefulNode(template.Node):
def __init__(self, key, nodes):
Stateful[key] = nodes
def render(self, context):
return ''
register.tag('set', do_set)
def do_get(parser, token):
tag_name, key = token.split_contents()
return GetStatefulNode(key)
class GetStatefulNode(template.Node):
def __init__(self, key):
self.key = key
def render(self, context):
return ''.join( [x.render(context) for x in Stateful[self.key]] )
register.tag('get', do_get)
Then set values in one template via {% set foo %}put data here{% endset %}
and get them via {% get foo %}
in another.
- [Django]-Multiple Database Config in Django 1.2
- [Django]-Django dynamic model fields
- [Django]-When saving, how can you check if a field has changed?
3👍
I too have come across the same need for a repeated {% block %} in my template files. The issue is that I want a Django {% block %} to be used in either case of a Django conditional, and I want the {% block %} to be over-writable by subsequent files that may extend the current file. (So in this case, what I want is definitely more of a block than a variable because I’m not technically re-using it, it just appears on either end of a conditional.
The Problem:
The following Django template code will result in a Template Syntax Error, but I think it’s a valid “want” to have a defined {% block %} re-used in a conditional (IE, why is the Django parser validating syntax on BOTH ends of a conditional, shouldn’t it only validate the TRUTHY condition?)
# This example shows a {{ DEBUG }} conditional that loads
# Uncompressed JavaScript files if TRUE
# and loads Asynchronous minified JavaScript files if FALSE.
# BASE.html
{% if DEBUG %}
<script src="{{MEDIA_URL}}js/flatfile.1.js"></script>
<script src="{{MEDIA_URL}}js/flatfile.2.js"></script>
<script src="{{MEDIA_URL}}js/flatfile.3.js"></script>
<script type="text/javascript">
{% block page_js %}
var page = new $site.Page();
{% endblock page_js %}
</script>
{% else %}
<script type="text/javascript">
// load in the PRODUCTION VERSION of the site
// minified and asynchronosly loaded
yepnope([
{
load : '{MEDIA_URL}}js/flatfiles.min.js',
wait : true,
complete : function() {
{% block page_js %} // NOTE THE PAGE_JS BLOCK
var page = new $site.Page();
{% endblock page_js %}
}
}
)];
</script>
{% endif %}
# ABOUT.html
{% extends 'pages/base.html' %}
{% block page_js %}
var page = new $site.Page.About();
{% endblock page_js %}
The Solution:
You can use an {% include %} to conditionally insert a {% block %} more than once. This worked for me because the Django syntax checker includes only the TRUTHY {% include %}. See the result below:
# partials/page.js
{% block page_js %}
var page = new $site.Page();
{% endblock %}
# base.html
{% if DEBUG %}
<script src="{{MEDIA_URL}}js/flatfile.1.js"></script>
<script src="{{MEDIA_URL}}js/flatfile.2.js"></script>
<script src="{{MEDIA_URL}}js/flatfile.3.js"></script>
<script type="text/javascript">
{% include 'partials/page_js.html' %}
</script>
{% else %}
<script type="text/javascript">
yepnope([
{
load : '{MEDIA_URL}}js/flatfiles.min.js',
wait : true,
complete : function() {
{% include 'partials/page_js.html' %}
}
}
)];
</script>
{% endif %}
- [Django]-Extend base.html problem
- [Django]-How to access request body when using Django Rest Framework and avoid getting RawPostDataException
- [Django]-Django can' t load Module 'debug_toolbar': No module named 'debug_toolbar'
1👍
There are two easy solutions for this.
The easiest is to put your title into a context variable. You would set the context variable in your view.
If you are using something like generic views and don’t have a views.py for pictures, cats, etc. then you can go the way of a custom template tag that sets a variable in the context.
Going this route would enable you to do something like:
{% extends "base.html" %}
{% load set_page_title %}
{% page_title "My Pictures" %}
...
Then in your base.html:
...
{% block title %}{{ page_title }}{% endblock %}
...
<h1>{{ page_title }}</h1>
- [Django]-Django template how to look up a dictionary value with a variable
- [Django]-Django: Filter a Queryset made of unions not working
- [Django]-Adding css class to field on validation error in django
0👍
The selected answer alludes to an easy workaround to wrap one tag inside another in the child template to give them both the same value. I use this for social images like so.
Child template:
{% extends 'base.html' %}
...
{% block meta_image %}
{% block meta_image_secure %}
{% if object.cover_pic %}
{{ object.cover_pic.url }}
{% else %}
https://live-static.welovemicro.com/static/img/device-dark.png
{% endif %}
{% endblock %}
{% endblock %}
...
Then in the parent base.html
:
...
<meta property="og:image" itemprop="image" content="{% block meta_image %}https://live-static.welovemicro.com/static/img/device-dark.png{% endblock %}">
<meta property="og:image:secure_url" itemprop="image" content="{% block meta_image_secure %}https://live-static.welovemicro.com/static/img/device-dark.png{% endblock %}">
...
- [Django]-How to add a cancel button to DeleteView in django
- [Django]-Django: Safely Remove Old Migrations?
- [Django]-Suddenly when running tests I get "TypeError: 'NoneType' object is not iterable
0👍
I would suggest using the django-macros library.
To install:
pip install django-macros
And then add the 'macros'
app in your INSTALLED_APPS
list in settings.py
.
After that, load the macros custom tags in your base template and use them like that:
{# base.html #}
{% load macros %}
{% macro title %}
{% block title %} My Cool Website {% endblock %}
{% endmacro %}
<html>
<head>
<title> {% use_macro title %} </title>
</head>
<body>
<h1> {% use_macro title %} </h1>
</body>
</html>
- [Django]-What is the difference between cached_property in Django vs. Python's functools?
- [Django]-How to combine multiple QuerySets in Django?
- [Django]-Django – How to set default value for DecimalField in django 1.3?
-3👍
In twig you can make this like:
# base.html
<html>
<head>
<title>{{ block('title') }}</title>
</head>
<body>
<h1>{{ block('title') }}</h1>
</body>
</html>
# 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 %}
- [Django]-How can I access environment variables directly in a Django template?
- [Django]-Chained method calls indentation style in Python
- [Django]-How to remove all of the data in a table using Django