Hacker News new | past | comments | ask | show | jobs | submit login

The 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.



The 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") }}


>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.


Unfortunately, the defaults stink. 1.2 remedies this for error messages at least.

as_p and co. should include some class describing the field type in the outer <p> tag so that a developer can style the label and error messages in a way specific to the field type.


I agree that this is pretty frustrating - it's one of the things my django-html package addresses: http://github.com/simonw/django-html

    {% field form.name class="myclass" %}


I 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.


I'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.




Consider applying for YC's Spring batch! Applications are open till Feb 11.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: