пятница, 5 октября 2007 г.

Универсальные списки в django

Django пропагандирует девиз "less code is better", благодаря которому есть такая штука, как generic views. Но generic views, уменьшая код на python, приводят к тому, что дублирование проявляется в шаблонах. Чтобы его не было, придется позаимствовать подход из интерфейса администратора django:

1. View должен оперировать собственно классом модели и его метаинфомацией:
def object_list(request, modelname):
model = get_model('', modelname)
return render_to_response('object_list.html',
{'fields': model._meta.fields,
'class_name': model._meta.verbose_name_plural,
'object_list': model.objects.all()})


2. Тогда в самом шаблоне можно не только строить цикл
for object in object_list
но и цикл
for field in fields

3. В этом случае так просто получить значение поля не получится и придется написать фильтр:
def display_value(model, field):
return getattr(model, field.name)
register.filter('display_value', display_value)

Соответственно в шаблоне можно использовать конструкцию:
object|display_value:field

4. Этот код прекрасно работает с обычными полями, но для списков выбора (choices) возвращает хранимое, а не отображаемое значение. Значит придется вытаскивать список выбора и находить по хранимому значению отображаемое:
def display_value(model, field):
stored_value = getattr(model, field.name)
if field._choices == []:
return stored_value
else:
return filter(lambda choice, value=stored_value:
choice[0]==value, field._choices)[0][1]

Можно конечно написать и именованную функцию (или вообще, применить обычный цикл вместо фильтрации).