Django Templates: Using the "with" statement and "block.super" together

2,334 views
Skip to first unread message

Warren Smith

unread,
Sep 24, 2013, 1:59:27 PM9/24/13
to django...@googlegroups.com
On occasion, I've used the following technique in my django templates:

# parent.html 

{% block someblock %}
…stuff…
  {% if cool_optional_feature_is_enabled %}
    …optional stuff...
  {% endif %}
…stuff...
{% endblock %}


# child.html
{% extends "parent.html" %}

{% block someblock %}
  {% with True as cool_optional_feature_is_enabled %}
    {{ block.super }}
  {% endwith %}
{% endblock %}


The cool thing is that this technique allows a child template to essentially enable a feature in the parent template. The same technique can also be used to disable a feature in the parent template, or really anything that can be driven from a context variable, since, as I understand it, that is what the with statement is doing: temporarily injecting a variable into the context within which the expressions in a chunk of template code are evaluated against.

I was showing this to a colleague today and, though he thought it was neat, he had never seen it before and was concerned that it was not a mainstream use of the django template language. I did some cursory google searches and couldn't find any overt references to this ability either.

My concern is that I may be relying on some undocumented side-effect of the way that blocks or the with statement are implemented and that, at some point in the future, this will be changed and all of my templates that use this will break.
 

Bill Freeman

unread,
Sep 24, 2013, 3:03:59 PM9/24/13
to django-users
This sounds safe to me.  After all, we pass context variables in from views and expect them to be available within block.super code.

Perhaps some folks aren't sufficiently clear as to when stuff in a template is evaluated.

So, I'd do it if I needed it.


--
You received this message because you are subscribed to the Google Groups "Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-users...@googlegroups.com.
To post to this group, send email to django...@googlegroups.com.
Visit this group at http://groups.google.com/group/django-users.
For more options, visit https://groups.google.com/groups/opt_out.

Tomas Ehrlich

unread,
Sep 24, 2013, 3:21:03 PM9/24/13
to django...@googlegroups.com
I use it too.

Maybe it would be nice to document it somewhere.


Cheers,
Tom


Dne Tue, 24 Sep 2013 10:59:27 -0700 (PDT)
Warren Smith <war...@wandrsmith.net> napsal(a):
signature.asc

Vijay Katam

unread,
Sep 24, 2013, 6:42:46 PM9/24/13
to django...@googlegroups.com
Seems legit to me. Some documentation could help get more usage.

Russell Keith-Magee

unread,
Sep 24, 2013, 9:27:35 PM9/24/13
to Django Users
As far as I can make out, this is exactly how blocks are intended to work -- you're not relying on anything edge case here.

Finding documentation for this will be a little hard, because it's a bit of an abstract concept. However, there have been plenty of tickets closed as "not a bug" around related template parsing issues.

At the core of why this works -- In conceptual terms, template blocks have higher precedence than any other tag in Django's template language. Blocks are resolved first; once blocks have been resolved the rest of the template, and all other template tags, are resolved with equal precedence. (It's a little more complex than this when you get to the internals, but this will do as a first-order approximation of what happens).

So in this case -- the block set up a structure that puts the content of the parent into child.html, which means, as you put it, the child enables a feature in the base.

Yours,
Russ Magee %-)
Reply all
Reply to author
Forward
0 new messages