По логике, следующим шагом для ZContact была бы возможность добавлять контакты, через форму, которая спрашивала бы у нас имя и фамилию нового контакта. Мы можем генерировать такую форму с помощью schema (IContact), определенную нами в interfaces.py с использованием пакета z3c.form
3.1 Добавление z3c.form и z3c.formui в качестве зависимостей
Однако, прежде чем мы сможем использовать z3c.form, мы должны добавить ее в качестве зависимости к нашему приложению.
Чтобы добавить z3c.form как зависимость, откройте setup.py в корневой директории вашего приложения и добавьте 'z3.form' параметру install_requires (где-то возле 25 линии :). В это время вам следует также добавить z3c.formui и z3c.layer в качестве зависимостей, которые необходимы для отрисовки в клевой верстке.
Следующее, что вы захотите, это включить zcml-конфигурацию для z3c.form и z3c.formui в файл configure.zcml, расположенный в zcontact/src/configure.zcml. z3c.form makes use (делает применение?) другие многочисленные компоненты z3c.*, которые определяют новые zcml-директивы.
Для использования этих директив вы должны включить метафайлы в начало файла сonfigure.zcml перед всеми другими инклюдами (include).
Следующее, что вам нужно, это включить реально (?) пакеты z3c.form и z3c.formui в конец конфигурационного файла configure.zcml.
Теперь все, что мы должны сделать, это перезапустить процесс сборки, чтобы загрузились и стали доступны новые яйца-капсулы для z3c.form и z3c.formui.
$ ./bin/buildout -NОпция -N указана для того, чтобы не загружались уже скачанные яйца (настоятельно рекомендуется).
3.2 Настройка вашего приложения для работы с z3c.form
К сожалению, мы еще не совсем готовы к использованию z3c.form. Из-за того, что пакеты z3c созданы с неким другим шаблоном для создания приложений, необходимы ее кое-какие шаги, чтобы заставить их работать. Одним из таких шагов будет установка своего собственного слоя и скина. К несчастью, многие zcml-директивы не помогут вам объяснить, для какого слоя вам необходимо зарегистрировать страницу или вид. Если вы не укажете слой, он регистрируется со слоем по-умолчанию. Это отключит все те пакеты, которые зарегистрировали все свои собственные виды со слоем по-умолчанию, делая этот слой сильно загрязненным всяким ненужным нам барахлом. Избежать этого непотребства, пакеты z3c.* регистрируют все свои виды по запросу на слое, специфичному (?) пакету. Чтобы правильно использовать z3c.* пакет, вы должны расширить эти слои со своим собственным. Сейчас мы создадим слой, который позволит нам использовать виды из пакета z3c.form.
3.2.1 Создание слоя
Создайте новый файл src/zcontact/layer.py и добавьте в него следующий код:
1 | from z3c.form.interfaces import IFormLayer |
IFormLayer имеет виды для всех виджетов, используемых в генерируемых формах, а IPageletBrowserLayer предоставляет различные полезные виды утилит, таких как error.
3.2.2 Создание скина
Чтобы получить доступ к этому слою из браузера, мы должны создать скин. Итак, создадим еще один файл src/zcontact/skin.py и добавьте туда следующий код:
1 | import z3c.formui.interfaces |
Заметьте, что наш скин наследуется от IDivFormLayer, определенный в пакете z3c.formui. Когда форма отрендерится, поля возникнут в тегах, а не в таблице. Существует еще слой для верстки, основанной на таблицах. Благодаря компонентной архитектуре, также возможно написать свой собственный слой верстки форм, но мы не будем здесь этого делать. :)
Сейчас мы должны зарегистрировать скин в zcml с новым файлом src/zcontact/skin.zcml. Мы сделаем доступным наш скин через http://localhost:8080/++skin++ZContact/. В файле будет следующее:
Не забудьте включить этот новый zcml-файл в zcontact/configure.zcml линией
3.3 Создание формы добавления
Мы начнем создание нового модуля zcontact.browser, добавив директорию browser в src/zcontact с пустым файлом __init__.py. Теперь мы можем создать и открыть новый файл zcontact/browser/contact.py, где мы определим все формы.
Начнем с добавления следующего кода в файл browser/contact.py:
1 | from z3c.form import form, field |
Затем мы добавим страницу, которая использует этот класс для отображения ормы. Откройте zcontact/browser/configure.zcml и добавьте следующее:
1 |
|
Теперь мы готовы к действию, итак, перезапустим сервер с помощью команды ./bin/paster serve deploy.ini (или debug.ini, если пожелаете) и зайдем по адресу http://localhost:8080/++skin++ZContact/@@addContact.html. Вы должны увидеть очень простую форму по типу:
3.4 Доводим до конца форму добавления
Если вы действительно попробовалииспользовать форму добавления и нажимали на кнопку, вы должны были получить ошибку NotImplemented. Если вы выбирали запуск paster с конфигурацией debug.ini, а не deploy.ini, вероятно вы получали клевый (прикольный) экран по типу следующего:
Из этово экрана вы можете раскрыть любую строчку в трассировке и вставить туда код python, чтобы отладить проблему. Я был очень удивлен (и я тоже, - прим. переводчика), когда впервые увидел это.
Чтобы исправить ошибку, мы должны реализовать три метода для класса ContactAddForm: create, add и nextURL. Я решил реализовать то по-быстрому, как показано ниже, хотя, конечно, никто не мешает вам сделать это по-своему.
1 | from z3c.form import form, field |
В методе create мы использовали функцию form.applyChanges для установки значений атрибутов нового контакта firstName и lastName. Данные, передаваемые методу create соотносятся между именами полей и введенными данными, уже приведенными к правильным типам python. Например, мы должны получить contact.firstName = data['firstName']. Я жестко установил методу nextURL возвращать путь, который отправлял бы нас назад к скину по-умолчанию Rotterdam, где вы сможете увидеть заново созданный контакт в виде содержимого. Мы сделали это, так как еще не написали свой собственные контентные виды для нашего слоя/скина и должны возвращаться в Rotterdam.
3.5 Формы отображения и редактирования
Формы отображения и редактирования еще проще, чем формы добавления, тк как вам не нужно реализовывать дополнительные методы. Давайте начнем с создания такой формы отображения.
3.5.1 Создание формы отображения
Для создания формы отображения нам понадобится новый класс, который бы наследовался от form.Form. Чтобы виджет отображался как обычный текст, а не форма ввода, мы должны установить для формы режим DISPLAY_MODE, это обычная константа, которую нужно импортировать из z3c.form.interfaces, (добавив строку импорта from z3c.form.interfaces import DISPLAY_MODE - прим. переводчика). Откройте файл zcontact/browser/contact.py и добавьте следующий код:
1 | class ContactDisplayForm(form.Form): |
и не забудьте зарегистрировать новую форму в configure.zcml (не который корневой, а который в папке browser - прим. переводчика) с помощью следующего:
1 |
|
Сейчас, когда у нас есть форма отображения, мы можем изменить nextURL класса ContactAddForm, чтобы он указывал на вновь созданный контакт. Теперь он будет выглядеть следующим образом:
1 | def nextURL(self): |
Не забудьте включить линию from zope.traversing.browser.absoluteurl import absoluteURL в начало файла! Если все получилось, вы можете рестартовать сервер и добавить новый контакт по адресу http://localhost:8080/++skin++ZContact/@@addContact.html, чтобы открыть форму отображения. Она будет выглядеть примерно так:
3.5.2 Добавление кнопок в форму
А теперь давайте-ка добавим две кнопочки, одну для редактирования, другую для удаления контакта. Начнем с добавления строчки from z3c.form import button в начало файла contact.py.
Когда пользователь нажимает кнопку, данные формы отправляются по адресу url, указанному в атрибуте action формы. По-умолчанию, action установлено в url самой формы, так что, когда нажимаем кнопку, порма просто перезагружается. Когда форма отрабатывается, проверяется, какая кнопка была нажата и вызываются соответствующие обработчики (handlers), которые определены как методы в классе ContactDisplayForm. Кроме того, при помощи z3c.form мы можем определить кнопку и обработчик, используя декоратор. Для кнопки удаления мы заходим удалить контакт и отправить пользователя назад на форму добавления. Добавим следующий код в класс ContactDisplayForm:
1 | @button.buttonAndHandler(u'Delete', name='delete') |
Убедитесь, что вы добавили следующие строчки импорта в начало файла:
1 | from z3c.form import form, field, button |
Действительно, если ее упустить, то в дебаг-мод можно увидеть трейссинг следующего вида:
А еще конечно же не забываем про from zcontact import interfaces. Таким образом, у нас будет наверху следующий импорт:
from zope.traversing.browser.absoluteurl import absoluteURL
from z3c.form import form, field, button
from z3c.form.interfaces import DISPLAY_MODE
from zcontact import interfaces
from zcontact.contact import Contact
from zope.traversing.api import getParent, getName
Так что смотрим внимательно за тем, что делаем! - прим. переводчика)
Теперь добавим кнопку редактирования. У нас еще нет пока формы редактирования, так что кнопка редактирования будет вести нас на несуществующую страницу. Пока просто забьем место этим. Добавьте следующее в класс ContactDisplayForm:
1 | @button.buttonAndHandler(u'Edit', name="edit") |
Теперь вы можете рестартовать сервер и попробовать кнопки (Зайдите по адресу http://localhost:8080/++skin++ZContact/@@addContact.html, добавьте контакт и полюбуйтесь - прим. переводчика). Ваша форма будет похожа на следующую:
3.5.3 Создание форм для редактирования
К этому времени вы должны быть близки к уровню профи в деле автогенерируемых форм. Нашим финальным аккордом будет создание формы редактирования, которая самая простенькая из всех. Вот код, который вам нужно добавить:
1 | class ContactEditForm(form.EditForm): |
1 |
|
1 | @button.buttonAndHandler(u'Done', name='done') |
3.6 Завершение приложения заглавной страницей
Прежде чем мы ринемся в скиннинг, давайте сделаем еще одну страницу для целостности нашего приложения. Следующая страница будет заглавной страницей нашего приложения и будет предоставлять ссылку на форму добавления и ссылки на каждый существующий контакт. Это все можно сделать в простом шаблоне в zcontact/browser/frontpage.pt
Чтобы это появилось в главной странице нашего приложения, нам нужно зарегистрировать страницу в zcml для интерфейса IRootFolder. Добавим следующее в файл zcontact/browser/configure.zcml:
Перезагрузите ваш сервер и проверьте http://localhost:8080/++skin++ZContact/ и вы должны увидеть что-то похожее.
Итак, с несколькими готовыми формами и сносно работающим приложеньицем, мы можем начать изучение других пакетов z3c.*.