22 ноября 2011

готовим Pylons + WTForms

WTForm простая, но довольно удобная библиотека для создания форм. И еще WTForm очень похожа на формы в Django - одно из немногово что в джанге сделано хорошо. Посмотрим как это работает с Pylons. Для удобства будем хранить формы отдельно
|+config/
|+controllers/
|~forms/
| |~mycontroller/
| | |-__init__.py
| | `-equipments.py
| |+validators/
| `-__init__.py
Создаем форму для редактирования оборудования equipments.py
from myapp.model.meta import Session as s
from myapp.model.mymodel import EquipmentType
from wtforms import Form, TextField, validators
from wtforms.ext.sqlalchemy.fields import QuerySelectField

# Выбор всех разновидностей оборудования для списка type в форме
def all_equipment_types():
    return s.query(EquipmentType).all()

class EditForm(Form):
    ip = TextField('ip address')
    netmask = TextField('network mask')
    mac = TextField('mac address')
    type = QuerySelectField('type of equipment',
                            query_factory=all_equipment_types)
QuerySelectField это поле из расширения WTForm для SQLAlchemy, которое позволяет создавать списки на основе выборок. Также есть расширения для Django и GAE. Инициализируем нашу форму в контроллере и передадим шаблону
from myapp.forms.mycontroller.equipments import EditForm

class EquipmentsController(BaseController):
    ...
    def edit(self, id, format='html'):
        """GET /myapp/equipments/id/edit: Form to edit an existing item"""
        # url('myapp_edit_equipment', id=ID)
        c.equipment = s.query(Equipment).filter(id==id)
        c.form = EditForm(ip=c.equipment.ip, mac=c.equipment.mac,
                        type=c.equipment.equipmenttype,
                        netmask=c.equipment.netmask)

        return render('/myapp/equipments/edit.html')
После передачи одноименных полям параметров в форму, значения этих параметров будут по умолчанию выведены в форме. Напишем шаблон на Jinja
{% extends "base.html" %}

{% block content %}
<form action="{{ url(controller='myapp/equipments', action='update', id=c.equipment.id) }}" method="POST">
<table class="simpletable">
<caption>Edit equipment of {{ c.equipment.equipmenttype }}
    ({{ c.equipment.ip }})</caption>
<tbody>
{% for field in c.form.data %}
<tr><td>{{ c.form[field].label }}</td>
    <td>{{ c.form[field] }}</td>
</tr>
{% endfor %}
<tr><td colspan="5">
<button><img src="/img/common/save.png" />Save</button>
<input type="hidden" name="_method" value="PUT" />
</td></tr>
</tbody>
</table>
</form>
{% endblock %}
В примере поля выводятся в цикле из списка form.data. Я использую REST контроллеры поэтому обновление происходит в методе update
from myapp.forms.mycontroller.equipments import EditForm

class EquipmentsController(BaseController):
    ...
    def update(self, id):
        """PUT /myapp/equipments/id: Update an existing item"""
        # Forms posted to this method should contain a hidden field:
        #    
        # Or using helpers:
        #    h.form(url('myapp_equipment', id=ID),
        #           method='put')
        # url('myapp_equipment', id=ID)
        equipment = s.query(Equipment).filter(id=id)
        if request.POST['ip']:
            equipment.ip = request.POST['ip']
        if request.POST['netmask']:
            equipment.netmask = request.POST['netmask']
        if request.POST['mac']:
            equipment.mac = request.POST['mac']
        type = EquipmentType.by_id(request.POST['type'])
        equipment.equipmenttype = type
        s.commit()

        came_from = str(request.environ.get('HTTP_REFERER', '')) or url('/')

        redirect(came_from)
Последние две строки возвращают пользователя обратно на страницу редактирования. Выглядит это как-то так:
Пример WTForm и Pylons

Комментариев нет:

Отправить комментарий