5 ms·
Absolutely agree. Writing template tags in Django involves a lot of boilerplate. Compare for example Mako or Jinja2 where you can easily write a macro to handle
by zeemonkee 16y ago
Absolutely agree. Writing template tags in Django involves a lot of boilerplate. Compare for example Mako or Jinja2 where you can easily write a macro to handle something like nested comments.
- kingkilr 16y agoFWIW it's pretty easy to write a {% macro %} tag for Django: http://alexgaynor.net/2008/dec/25/building-a-function-templatetag/ http://alexgaynor.net/2008/dec/25/building-a-function-templa...
- zeemonkee 16y agoSure, but that's a workaround for something that arguably belongs in the template language to start with.
- kingkilr 16y agoWell, that's a matter of perspective. In any event if this were to be implemented in the Django template language it would be implemented as a tag like this, just as {% for %}, {% if %} and everything else are. Everything is a first class citizen :)
- metamemetics 16y agoYou can already drop in a nested comments system with Pinax super easy. But if you want to write your own, use {% include %} tag to render them recursively using multiple templates. This also allows you to implement AJAX loading\closing of subcomments much easier than if you came up with some macro to display\load every single comment in one template
- erlanger 16y agoThe included simple_tag and filter decorators should be used for simple tags and filters. More sophisticated tags can specify a separate renderer class, which must be what you mean by "boilerplate." from django.core.urlresolvers import reverse from django.template import Library register = Library() @register.simple_tag def menu_item(req, viewname, label): url = reverse(viewname) cls = '' if url == req.path: cls += 'active' return '<li class="%s"><a href="%s">%s</a></li>' % (cls, url, label) Using the tag: {% menu_item request 'accounts.views.profile' 'Your Account' %} The only part of that I don't like is passing the request, but I'm willing to bet there's a simpler way to access the request object from the function. A simple filter: @register.filter def subtract(x, y): """Subtracts the arg from the value""" return int(x) - int(y) And maybe in a for loop for overlapping elements: <li style="z-index: {{ 100|subtract:forloop.counter }}"> Yes, I use two spaces in my Python code too.
- stevenwei 16y agoI'm not really a big fan of how writing custom template tags throws you back into the land of string substitution: the entire problem that templating languages were meant to solve in the first place! Jinja2's macros are a much more elegant solution, IMO.
- zeemonkee 16y agoThe above solution is just plain ugly, HTML in Python. Another PITA, where Django templates just fall down, is forms. Suppose you have a form: class MyForm(forms.Form): name = forms.CharField() You then add that in the template: {{ form.name }} All well and good; but what if you want to change the size, maxlength, or add a class ? These things clearly belong in the template, but no, you have to either add them in the form declaration: name = forms.CharField(widget=forms.TextInput(attrs={'class' : 'foo'})) or in the view: form.fields['name'].widget.attrs = {'class' : 'foo'} Both of which clearly break the separation of concerns. yes, you could write a template tag to get around this; but it's not in standard Django. Contrast the following in Jinja2 (using WTForms, but you get the idea): {{ form.name(class_="foo") }}
- simonw 16y agoI agree that this is pretty frustrating - it's one of the things my django-html package addresses: http://github.com/simonw/django-html http://github.com/simonw/django-html {% field form.name class="myclass" %}
- zeemonkee 16y agoI had a similar workaround in a project, it did something like this: {% form.name|attrs:"class='foo', maxlength=20" %} If Django templates allowed function calls however (as Jinja2 does) that would eliminate the need for a lot of these tags.
- metamemetics 16y ago>All well and good; but what if you want to change the size, maxlength, or add a class ? Adding a class: Django gives every element of the form id values for easy styling in CSS. Just do {{form.as_p}} and see what it outputs. size and max length: I'm fine with these in python as they correspond to the max-length that would be validated into a data member. If you mean pixel size on screen, this belongs neither in HTML or your template but in CSS, since browsers render forms completely differently regardless of their HTML attributes, you have to style their width\height in CSS to get anything consistent.