Как стать автором
Обновить

Оформляем формы

Время на прочтение3 мин
Количество просмотров21K
У форм в Django есть несколько предопределенных методов as_p(), as_table() и as_ul(), которые отображают форму как набор параграфов, таблицу или список. На практике этих методов не всегда достаточно, чтобы формы выглядели так, как нам хочется.

Допустим, верстальщик сверстал все формы div-ами. Документация предлагает в этом случае писать нужные теги в ручную в шаблоне. Если форма у нас только одна, можно поступить и так. Если форм несколько, то этот подход сразу же теряет все свое очарование. Решение очень простое — пронаследуем наш собственный класс форм от forms.Form или forms.ModelForm и обучим его рисовать формы так, как нужно нам.

Для начала неплохо заглянуть в исходники Django – методы as_p и ему подобные устроены очень просто. Они вызывают метод _html_output класса BaseForm инструктируя его, как именно рисовать форму. Итак, добавим свой метод as_div:
Copy Source | Copy HTML
  1. class SexyModelForm(forms.ModelForm):
  2.     def as_div(self):
  3.         return self._html_output(
  4.             normal_row = u'<div%(html_class_attr)s>%(label)s %(field)s %(help_text)s %(errors)s</div>',
  5.             error_row = u'<div class="error">%s</div>',
  6.             row_ender = '</div>',
  7.             help_text_html = u'<div class="hefp-text">%s</div>',
  8.             errors_on_separate_row = False)

Код самоочевиден, единственное, что может вызвать вопросы — это errors_on_separate_row. Если этот параметр установлен в True, то ошибки будут выводиться отдельным блоком. Он используется, например в as_p, чтобы не запихивать <ul> внутрь <p>.

Теперь, мы можем наследовать наши формы от SexyModelForm и вызывать их в шаблонах с помощью {{ form.as_div }}.

В 1.2. появилась приятная возможность назначать свои css-классы для обязательного поля и поля с ошибкой. Еще немного упростим себе жизнь — допишем пару строк в наш класс, и в формы добавится еще немного единообразия:
Copy Source | Copy HTML
  1. error_css_class = 'class-error'
  2. required_css_class = 'class-required'

Но и это еще не все. Бывает нужно добавить всем полям какие-то css-классы. Это можно сделать вот так:
Copy Source | Copy HTML
  1. def __init__(self, *args, **kwargs):
  2.     super(ModelForm, self).__init__(*args, **kwargs)
  3.         # adding css classes to widgets without define the fields:
  4.         for field in self.fields:
  5.             self.fields[field].widget.attrs['class'] = 'some-class other-class'

Здесь-же можно, например, проверять input_type и присваивать классы разным типам полей в зависимости от него.

Вот, что получилось в итоге:
Copy Source | Copy HTML
  1. class SexyModelForm(forms.ModelForm):
  2.     error_css_class = 'class-error'
  3.     required_css_class = 'class-required'
  4.     def __init__(self, *args, **kwargs):
  5.         super(ModelForm, self).__init__(*args, **kwargs)
  6.         # adding css classes to widgets without define the fields:
  7.         for field in self.fields:
  8.             self.fields[field].widget.attrs['class'] = 'some-class other-class'
  9.     def as_div(self):
  10.         return self._html_output(
  11.             normal_row = u'<div%(html_class_attr)s>%(label)s %(field)s %(help_text)s %(errors)s</div>',
  12.             error_row = u'<div class="error">%s</div>',
  13.             row_ender = '</div>',
  14.             help_text_html = u'<div class="hefp-text">%s</div>',
  15.             errors_on_separate_row = False)

Решение получилось простое, не захламляющее код и работоспособное.
Теги:
Хабы:
Всего голосов 51: ↑41 и ↓10+31
Комментарии25

Публикации

Истории

Работа

Python разработчик
140 вакансий

Ближайшие события

27 августа – 7 октября
Премия digital-кейсов «Проксима»
МоскваОнлайн
11 сентября
Митап по BigData от Честного ЗНАКа
Санкт-ПетербургОнлайн
19 сентября
CDI Conf 2024
Москва
24 сентября
Конференция Fin.Bot 2024
МоскваОнлайн
25 сентября
Конференция Yandex Scale 2024
МоскваОнлайн
28 – 29 сентября
Конференция E-CODE
МоскваОнлайн
28 сентября – 5 октября
О! Хакатон
Онлайн
30 сентября – 1 октября
Конференция фронтенд-разработчиков FrontendConf 2024
МоскваОнлайн