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.
