Django поставляется с библиотекой для работы с формами, она находится в модуле django.forms и может решать множество задач, которые мы рассмотрим в этой главе — от отображения форм до проверки полей. Давайте переработаем наше приложение с контактной формой, используя эту библиотеку.
Библиотека newforms
Общаясь в Django сообществе, вы могли услышать о django.newforms. Так раньше называлась стандартная библиотека django.forms — эта библиотека рассматривается в данной главе.
Причина такого переименования историческая. Первый релиз Django поставлялся со сложной, запутанной библиотекой для работы с формами — django.forms. Она была полностью переписана и новая версия имела имя django.newforms, люди могли использовать как одну, так и другую библиотеки. После выхода Django 1.0 старая библиотека была убрана, а django.newforms стала django.forms.
Основным способом использования библиотеки является определения
класса Form для каждого тега
<form> в ваших шаблонах. В нашем случае, у нас есть
только один такой тег, следовательно и класс нам надо создать
только один. Этот класс может располагаться в любой части кода,
даже в файле views.py, но, учитывая
соглашения Django сообщества, код класса следует располагать в
файле forms.py. Создайте этот файл рядом с
views.py и впишите следующее:
from django import forms
class ContactForm(forms.Form):
subject = forms.CharField()
email = forms.EmailField(required=False)
message = forms.CharField()
Синтаксис похож на синтаксис описания модели. Каждое поле формы
представлено потомками класса Field — в нашем случае используются
CharField и
EmailField — в виде атрибутов
класса Form. Каждое поле по умолчанию
является обязательным, таким образом, чтобы отменить это
поведение у поля email, мы используем атрибут
required=False.
Давайте перейдём в интерактивный интерпретатор Python и посмотрим, что этот класс может делать. Во-первых, он может отображать себя в виде HTML:
>>> from contact.forms import ContactForm
>>> f = ContactForm()
>>> print f
<tr><th><label for="id_subject">Subject:</label></th><td><input type="text" name="subject" id="id_subject" /></td></tr>
<tr><th><label for="id_email">Email:</label></th><td><input type="text" name="email" id="id_email" /></td></tr>
<tr><th><label for="id_message">Message:</label></th><td><input type="text" name="message" id="id_message" /></td></tr>
Django добавляет метку для каждого поля с помощью тега <label>. Идея состоит в том, чтобы сделать стандартное поведение наиболее оптимальным.
По умолчанию форма выводится в виде содержимого таблицы, но есть несколько встроенных опций:
>>> print f.as_ul()
<li><label for="id_subject">Subject:</label> <input type="text" name="subject" id="id_subject" /></li>
<li><label for="id_email">Email:</label> <input type="text" name="email" id="id_email" /></li>
<li><label for="id_message">Message:</label> <input type="text" name="message" id="id_message" /></li>
>>> print f.as_p()
<p><label for="id_subject">Subject:</label> <input type="text" name="subject" id="id_subject" /></p>
<p><label for="id_email">Email:</label> <input type="text" name="email" id="id_email" /></p>
<p><label for="id_message">Message:</label> <input type="text" name="message" id="id_message" /></p>
Следует отметить, что открывающие и закрывающие теги <table>, <ul> и <form> не указываются, значит вы можете сами добавить любую дополнительную запись при необходимости.
Эти методы являются простыми сокращениями для общей задачи «отображения всей формы». Вы можете также отобразить HTML для конкретного поля формы:
>>> print f['subject']
<input type="text" name="subject" id="id_subject" />
>>> print f['message']
<input type="text" name="message" id="id_message" />
Во-вторых, объекты Form могут проверять
пользовательские данные. Для этого, создайте новый объект
Form и передайте ему словарь с данными,
который соответствует именам полей формы:
>>> f = ContactForm({'subject': 'Hello',
'email': 'adrian@example.com',
'message': 'Nice site!'})
Теперь можно проверить каждому ли полю назначено значение:
>>> f.is_bound
True
Вызывайте метод is_valid() для
Form, чтобы проверить данные, переданные
форме. Мы передали верные данные для каждого поля, таким образом
форма должна быть правильной:
>>> f.is_valid()
True
Если мы не передадим поле email, форма по-прежнему останется верной, так как мы указали атрибут required=False для этого поля:
>>> f = ContactForm({'subject': 'Hello', 'message': 'Nice site!'})
>>> f.is_valid()
True
Но если мы не укажем subject или message, тогда форма перестанет быть верной:
>>> f = ContactForm({'subject': 'Hello'})
>>> f.is_valid()
False
>>> f = ContactForm({'subject': 'Hello', 'message': ''})
>>> f.is_valid()
False
Вы можете получить сообщения об ошибке для каждого поля:
>>> f = ContactForm({'subject': 'Hello', 'message': ''})
>>> f['message'].errors
[u'This field is required.']
>>> f['subject'].errors
[]
>>> f['email'].errors
[]
Каждый экземпляр Form имеет атрибут
errors, который хранит словарь со списком
сообщений для каждого поля:
>>> f = ContactForm({'subject': 'Hello', 'message': ''})
>>> f.errors
{'message': [u'This field is required.']}
Наконец, для экземпляров Form, данные
которых признаны верными, становится доступным атрибут
cleaned_data. Атрибут содержит словарь с
«чистыми» переданными данными. Библиотека для
работы с формами не только проверяет данные, но и может их
обрабатывать, конвертируя значения в соответствующие типы языка
Python.
>>> f = ContactForm({‘subject’: ‘Hello’, ‘email’: ‘adrian@example.com’, ‘message’: ‘Nice site!’})
>>> f.is_valid()
True
>>> f.cleaned_data
{‘message’: u’Nice site!’, ‘email’: u’adrian@example.com’, ‘subject’: u’Hello’}
Наша форма работает только со строками, которые конвертируются в
объекты Unicode — но если мы бы мы
использовали IntegerField или
DateField, библиотека бы предоставила в
cleaned_data соответствующие типы целого или
datetime.date объекты для соответствующих полей.
| Пред. | Уровень выше | След. |
| Создание формы для контактной информации | Начало | Используем формы в представлениях |
3 comments | Make a comment
Если следовать инструкциям по созданию файла forms.py, то далее строчку
"from contact.forms import ContactForm"
следует заменить на
"from forms import ContactForm"
Если forms и views находяться в contacts, то эти две строки будут работать аналогично.
Извиняюсь, невнимательно читал. Забыл, что в предыдущей главе мы создали отдельный каталог contact.