A common use case when developing Django templates is rendering a block only when the block has content. Take this for example:
<section id="message" class="messages alert"> | |
<p>{% block message %}{% endblock %}</p> | |
</section> |
If you use blocks as designed out of the box, you’ll end up with some extra markup that you may need to hide via other methods (such as CSS). That’s definitely not ideal.
After digging around for a bit I stumbled upon this very helpful snippet which accomplishes this using a custom template tag:
from django import template | |
register = template.Library() | |
@register.tag(name='captureas') | |
def do_captureas(parser, token): | |
try: | |
tag_name, args = token.contents.split(None, 1) | |
except ValueError: | |
raise template.TemplateSyntaxError("'captureas' node requires a variable name.") | |
nodelist = parser.parse(('endcaptureas',)) | |
parser.delete_first_token() | |
return CaptureasNode(nodelist, args) | |
class CaptureasNode(template.Node): | |
def __init__(self, nodelist, varname): | |
self.nodelist = nodelist | |
self.varname = varname | |
def render(self, context): | |
output = self.nodelist.render(context) | |
context[self.varname] = output | |
return '' |
The tag captures the content of the block to a variable within the template which can then be tested for existence, allowing you to conditionally show the block depending on the contents.
Using the tag is as simple as this:
{% load captureas %} | |
{% captureas message %}{% spaceless %}{% block message %}{% endblock %}{% endspaceless %}{% endcaptureas %} | |
{% if message %} | |
<section id="message" class="messages alert"> | |
<p>{{ message }}</p> | |
</section> | |
{% endif %} |
Hopefully Django adds this in the future.