Opened 10 years ago

Closed 9 years ago

#8296 closed (duplicate)

Allow template parser to parse until "complex" block node

Reported by: Julien Phalip Owned by: nobody
Component: Template system Version: master
Severity: Keywords:
Cc: me@… Triage Stage: Design decision needed
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no


For info, this was brought up in [1].

Currently, with block tags, you can only parse until a "simple" closure tag. For example: {% endif %} or {% endfor %}.

Now, it would be nice if you could parse until something more "complex" like {% elseif blah and blahblah %}. By "complex" I mean a tag that requires some parameters.

Here I'm not asking for an elseif tag in particular, but I'd like to allow the parser to also consider "complex" closure tags.

For example, a direct application of this would be a suggestion for a {% withblock %} tag. Here's a suggested syntax:

{% withblock as myurl %}
   {% url arg1,arg2,name1=value1 %}
{% and as var %}
   {% whatever %}
{% in %}
       Click the link: <a href="{{ myurl }}">{{ var }}</a>.
{% endwithblock %}

Currently the {% and as var %} tag cannot be recognized. The problem is in django.template.Parser.parse():

elif token.token_type == TOKEN_BLOCK:
    if token.contents in parse_until:

It basically checks if the tag's hard string name is in the list. The attached patch, which is *backward compatible*, only looks at the first piece of text in the node, namely the tag's name. With that, in your tag you could parse the block like follows:

    nodelist = parser.parse(('and', 'in')) # Parse until {% and as var %} or {% in %} 


Attachments (2)

8296.parser.diff (729 bytes) - added by Julien Phalip 10 years ago.
8296.diff (1.2 KB) - added by Andy Durdin 10 years ago.
Slightly more robust patch.

Download all attachments as: .zip

Change History (7)

Changed 10 years ago by Julien Phalip

Attachment: 8296.parser.diff added

comment:1 Changed 10 years ago by Julien Phalip

Just for the record, #8297 would make use of this change to implement a suggested {% withblock tag %}.

comment:2 Changed 10 years ago by Malcolm Tredinnick

Triage Stage: UnreviewedDesign decision needed

comment:3 Changed 10 years ago by (none)

milestone: post-1.0

Milestone post-1.0 deleted

comment:4 Changed 10 years ago by Andy Durdin

Cc: me@… added

In the meantime, here's a slightly ugly workaround that you can put in your tag:

    class BlockTagList(object):
        # This is a bit of a hack, as it embeds knowledge of the behaviour
        # of Parser.parse() relating to the "parse_until" argument.
        def __init__(self, *names):
            self.names = set(names)
        def __contains__(self, token_contents):
            name = token_contents.split()[0]
            return name in self.names

    # Skip over everything before the first {% case %} tag
    parser.parse(BlockTagList('case', 'endswitch'))

Changed 10 years ago by Andy Durdin

Attachment: 8296.diff added

Slightly more robust patch.

comment:5 Changed 9 years ago by Joey Wilhelm

Resolution: duplicate
Status: newclosed

Duplicate of #3090. In fact, the patch is almost identical.

Note: See TracTickets for help on using tickets.
Back to Top