Hello all,

For many years, writing templatetags has been among the most hilariously
complicated things we Django developers did. Anyone who has written parsing
for
templatetags, over and over, shares this pain. Further, the current syntax
present a tremendous problem for Armin Ronacher's GSOC towards template
compilation: template tags define a ``render()`` method, which takes the
current context (a stack of dictionaries) and perform some behavior which is
opaque to the caller. This is a problem because one of the core objectives
of
the template compilation infrastructure is to store the template context in
Python local variables, rather than in dictionaries. For all these reasons,
several of us (myself, Idan, Russ, Carl Meyer, Andrew Godwin, Jonas Obrist,
Chris Beaven) just sat down (we actually stood, mostly) and tried to iron
out a
proposal that solves these problems, taking inspiration from the plethora of
libraries that exist today.

We ultimately created two possible solutions, one inspired primarily by
django-classy-tags and django-templatetag-sugar, the other mostly inspired
by
django-ttags. We came to a fragile agreement on the first. We primarily
evaluated two cases for these, one very simple, the other more complex, and
compared the resulting implementations.

The first case we considered was a templatetag which takes two, required,
arguments. Invocation looks like ``{% mytag foo bar %}``.  The two
definitions
look like:

    class MyTag(Tag):
        args = [
            Argument("foo"),
            Argument("bar"),
        ]


    class MyTag(Tag):
        foo = Argument()
        bar = Argument()


the second case we considered was a tag which has one required, positional,
argument, and two optional, keyword arguments, which can occur in any order,
followed by a final, optional keyword argument, meaning any of the following
invocations are valid:

    {% mytag src limit 1 offset 10 %}
    {% mytag src limit 1 offset 10 with foo %}
    {% mytag src limit 1 %}
    {% mytag src offset 10 limit 1 %}
    {% mytag src %}

and the two implementations were:

    class MyTag(Tag):
        args = [
            Argument("source"),
            Unordered(
                NamedArgument("limit", required=False),
                NamedArgument("offset", required=False),
            ),
            NamedArgument("as", required=False, resolve=False)
        ]


    class MyTag(Tag):
        source = Argument()
        limit = NamedArgument(required=False)
        offset = NamedArgument(required=False)
        as_ = BasicArgument(required=False)

        class Meta:
            ordering = (
                ('source',),
                Unordered('limit', 'offset'),
                ('as_',)
            )

The general consensus was that the second implementation was *very* slightly
preferable in the simple case, however it was significantly more complicated
in
the second case, and thus the first implementation was preferable overall.

We notable did *not* discuss what the syntax for defining the output was, at
this stage we were only concerned with the syntax definition. This is
because
the actual ``render()`` equivalent will be orthogonal to the parsing stage
equivalent.

For your consideration,
Alex

-- 
"I disapprove of what you say, but I will defend to the death your right to
say it." -- Evelyn Beatrice Hall (summarizing Voltaire)
"The people's good is the highest law." -- Cicero

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

Reply via email to