#7324: {{ block.super }} doesn't work with nested {% block %} statements
--------------------------------------+-------------------------------------
          Reporter:  jeverling        |         Owner:  nobody              
            Status:  closed           |     Milestone:                      
         Component:  Template system  |       Version:  SVN                 
        Resolution:  invalid          |      Keywords:  block.super template
             Stage:  Unreviewed       |     Has_patch:  0                   
        Needs_docs:  1                |   Needs_tests:  0                   
Needs_better_patch:  0                |  
--------------------------------------+-------------------------------------
Changes (by lanyjie):

  * needs_docs:  0 => 1

Comment:

 There is lack of explicit specification on what should happen in the
 template system in some situations. The real issue here is this: when you
 have multiple definitions of the same block, what should happen? In the
 documentation, it simply says you should avoid such a situation in the
 same template, but when it happens, we should give a rule to resolve it.
 We first study the case when the definition of the same block is repeated
 in the child template (inheritance). The parent template comes first, and
 then the child template. And the implicit rule seems to be this: the first
 valid definition in the parent is the place holder (that is, whatever
 content is determined for this block shall be included in that place). The
 later definition will override the content, but not the location. So, this
 observation gives rise to a natural extension of this rule to resolve the
 issue of multiple definitions in a single file: the later definitions
 always override the content of the former ones, but only the first
 definition (note, this means no valid prior definitions exists) determines
 the place to include the final content. With this in mind, let's take a
 look at the test case above:

 {{{
 {% extends "new/test.html" %}
 {% comment %}Gets around infinite recursion bug by namespacing with a
 directory{% endcomment %}
 {% block main %}
     Top-level main block
     {% comment %}remove this block.super and it all disappears. But I only
 want the block.super from inside "submain"{% endcomment %}
     {{ block.super }}
     {% block submain %}
         my new sub-content
         {{ block.super }}
         {% comment %}I expect this block.super to contain the content of
 "submain" from new/test.html, because I'm extending it. It is empty,
 UNLESS "main" has a block.super call, in which case it's echoed TWICE{%
 endcomment %}
     {% endblock %}

 {% endblock %}
 }}}

 First note that the {{ block.super }} will include a definition of submain
 block, and since we are redefining the block "main" here, so the previous
 definition of block "submain" loses its meaning as a place holder (it is
 location-invalid as its definition context is invalidated), but its
 content is still meaningful. In this quite interesting case, the newly
 included definition becomes the new place holder definition. Then the new
 definition of "submain" is the second one in this same file, and according
 to our extended rule, it will only override the content of the first
 definition, but will not change the location of the block, nor shall it
 repeat the content at its own location. Then the logical output of this
 template naturally follows. One more subtle issue here: what should the {{
 block.super }} in the "submain" block be? Is it the content from the outer
 {{ block.super }}, or is it the one from the parent (note that the content
 there remains meaningful)? Well, it is probably not important here, as
 they are identical, but this is still an ambiguity that might cause
 trouble in other cases. One simple rule is: block.super always gives the
 content of the definition immediately precedes the current one, as the
 current one is overriding the former one. This is the rule I prefer, but
 people may go with the other way: that block.super always use the contents
 from the parent template. A problem with the latter approach is that we
 need new ways to access the contents of the same block defined earlier.
 Both ways yields the same result if no multiple definitions occur in a
 single template. I think multiple definitions in the same template might
 be useful as a content-holder, so that its contents may be used later
 through the block.super call as defined in the preferred way. It is then
 interesting to consider yet a slightly different situation:

 {{{
 {% extends "new/test.html" %}
 {% block main %}
     Top-level main block
     {% block submain %}
         my new sub-content
         {{ block.super }}
 {% comment %} request the content of a previous definition (in the parent
 template),
 it is OK as the former definition can still be used as a content-holder.
 this one
 is the place-holder, as the former becomes place-invalid. {% endcomment %}

     {% endblock %}

     {{ block.super }}
 {% comment %} request the content of a previous definition (in the parent
 template),
 which includes another definition of the "submain" block, which shall only
 override the contents of the former definition. The net result is that the
 new content
 of "submain" defined above is lost, replaced by the old content! {%
 endcomment %}

 {% endblock %}
 }}}

 In summary, a block definition has two properties: place and content. We
 should consider them
 in terms of place-holders and content-holders, and they could be place-
 valid, content-valid,
 place-invalid and/or content-invalid. The first definition will be place-
 holders unless it
 becomes place-invalid when its context is redefined. A later definition
 will make the former
 ones content-invalid. But it only becomes place-holders if all former ones
 become place-invalid.

 Please also refer to ticket #13399 for more discussions.

-- 
Ticket URL: <http://code.djangoproject.com/ticket/7324#comment:7>
Django <http://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To post to this group, send email to django-upda...@googlegroups.com.
To unsubscribe from this group, send email to 
django-updates+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-updates?hl=en.

Reply via email to