Field labels in templates
There’s no way in Django (that I’ve found) to render a field’s name in a
template. This means you end up with <th>Field Name</th>
all over your
templates. Why hello there, DRY violation!
The fields are stored in model._meta.fields
, but templates don’t allow you to
access variables which start with an underscore. I’ve got two little utility
functions I wrote for myself to generate a dict
of labels I can use in my
templates:
def get_labels_for(model, cap=True, esc=True):
from django.template.defaultfilters import capfirst
from django.utils.html import escape
labels = {}
for field in model._meta.fields:
label = field.verbose_name
if cap:
label = capfirst(label)
if esc:
label = escape(label)
labels[field.name] = label
return labels
def with_labels(context, cap=True, esc=True):
from django.db.models import Model
result = context.copy()
for k, v in context.iteritems():
if isinstance(v, Model):
result[k + '_labels'] = get_labels_for(v, cap, esc)
elif hasattr(v, '__getitem__') and len(v) > 0:
if isinstance(v[0], Model):
result[k + '_labels'] = get_labels_for(v[0], cap, esc)
return result
The parameters:
model
can be a model class or a model instance.- If
cap
isTrue
, the first letter of each label will be capitalized. - If
esc
isTrue
, the labels will be escaped for HTML.
So, in your view:
def some_view(request, foo_id):
foo = get_object_or_404(Foo, id=foo_id)
context = {'foo': foo, 'foo_labels': get_labels_for(foo)}
return render_to_response('foo.html', context)
And in your template:
{{ foo_labels.bar }}: {{ foo.bar }}
with_labels
works the same way, except you can just surround your context
with it:
def some_view(request, foo_id):
foo = get_object_or_404(Foo, id=foo_id)
bars = Bars.objects.all()
context = {'foo': foo, 'bars': bars}
return render_to_response('foo.html', with_labels(context))
It will detect the models and lists of models in the context and add
foo_labels
and bars_labels
to the context.