Хостинг Django от «Джино»
Table of contents

Ваш первый класс формы

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 объекты для соответствующих полей.

Winter 8 months ago
Answer Link

Извиняюсь, невнимательно читал. Забыл, что в предыдущей главе мы создали отдельный каталог contact.

alerion 8 months ago
Answer Link

Если forms и views находяться в contacts, то эти две строки будут работать аналогично.

Winter 8 months ago
Answer Link

Если следовать инструкциям по созданию файла forms.py, то далее строчку
"from contact.forms import ContactForm"
следует заменить на
"from forms import ContactForm"


Ищем Python программистов

Found misprint?
Select it with the mouse and hit Enter
Ctrl-Enter
Processed:
33 1 199 25


The full repository of DjangoBook translation you can get on GitHub.
We appreciate your patches!

We are glad to hear your questions, comments or suggestions!
(Open in new tab)

Users number: 601

Русская группа

на поддержку перевода
Яндекс Яндекс.Деньги Хочу такую же кнопку
Ускорить процесс перевода!
ЯМ:41001223475816


© 2008-2012 Ruslan Popov @ gmail.com Powered by Django 1.2.5