Tuesday, September 24, 2013

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


On Wed, Sep 25, 2013 at 1:59 AM, Warren Smith <warren@wandrsmith.net> wrote:
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.
 
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 %-)

--
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+unsubscribe@googlegroups.com.
To post to this group, send email to django-users@googlegroups.com.
Visit this group at http://groups.google.com/group/django-users.
For more options, visit https://groups.google.com/groups/opt_out.

No comments:

Post a Comment