On Fri, Sep 9, 2011 at 6:16 PM, Wim Feijen <[email protected]> wrote:

> Hi Alex,
>
> Probably I am thinking way too simple, but if you gave me a free
> choice of how to write templatetags in my code, I would prefer:
>
> def mytag(foo, bar):
>     # some code
>     return output
>
> or:
>
> class MyTag(Tag):
>    def __init__(self, foo, bar):
>        self.foo = foo
>        self.bar = bar
>
> and
>
> def mytag(src, limit=1, offset=10, ??)
>
> or:
>
> class MyTag(Tag):
>    def __init__(self, limit=1, offset=10, ??):
>        self.limit = limit
>        self.offset = offset
>
>   def render(self):
>   """do some nasty stuff to limit and offset and return something."""
>
> Just kick me if I am talking non-sense, that's ok.
>
> Wim
>
> On 10 sep, 02:29, Alex Gaynor <[email protected]> wrote:
> > 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.
>
>
This solution sounds nice, but it simply doesn't work for many examples.  a)
It fails to match the template language's understanding of what a node is
(they're created once at compilation time, and reused across all
invocations) and b) doesn't work with many types of arguments, for example
the argument form "{% foo limit 3 %}" where limit is some significant name,
passes some argument to this tag, this rather falls over in the case of
things like "{% foo limit 3 as bar %}" since as is a keyword in Python, and
finally it fails to express things like the sometimes ordered, sometimes
unordered nature of arguments.

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