Check if a block is defined in Django
Very often when styling a webpage, you want to put content in a box. For example, say you have a standard box for contextual help content.
<div class="help"> <!--- actual html contents here ---> </div> <style> .help { padding: 1em; border: 1px dashed black; } </style>
A sensible way to make this re-usable in Django would be to use blocks.
<div class="help"> {% block help %}{% endblock %} </div>
But what happens if no help block is defined? With this implementation, you would still get the empty help DIV, complete with a border and padding. Of course, you could render the div inside the block, but then you're repeating yourself every time you define one.
One work-around is via css:empty.
<style> .help:empty { disply: none; } </style>
However, that approach will not work in all browsers/versions. Also, it's muddying the separation between content and style.
Ideally, you would be able to omit the div at the base template level if the block is not defined. I wondered if there was an way to check if a block is defined. While hunting around, I found the next best thing. The following code (from kcarnold) will capture the contents of a block to a variable. You can then conditionally render it only if it exists and is not empty.
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 ''
{% captureas help_content %}{% spaceless %}{% block help %}{% endblock %}{% endspaceless %}{% endcaptureas %} {% if help_content %} <div id="help"> {{ help_content }} </div> {% endif %}
Django actually may add this functionality natively in the future.