The previous step was the smallest possible step into a Colander schema and Deform form based on that schema. Let’s take another very small step, but show processing the form.
$ cd ../../forms_schema; mkdir step02; cd step02
(Unchanged) Copy the following into step02/application.py:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | from wsgiref.simple_server import make_server
from pyramid.config import Configurator
def main():
config = Configurator()
config.scan("views")
config.add_static_view('deform_static', 'deform:static')
app = config.make_wsgi_app()
return app
if __name__ == '__main__':
app = main()
server = make_server(host='0.0.0.0', port=8080, app=app)
server.serve_forever()
|
Copy the following into step02/views.py:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | from pyramid.view import view_config
import colander
from deform import Form
from deform import ValidationFailure
class Person(colander.MappingSchema):
name = colander.SchemaNode(colander.String())
shoe_size = colander.SchemaNode(
colander.Integer(),
missing = 0,
)
class ProjectorViews(object):
def __init__(self, request):
self.request = request
@view_config(renderer="templates/site_view.pt")
def site_view(self):
schema = Person()
myform = Form(schema, buttons=('submit',))
if 'submit' in self.request.POST:
controls = self.request.POST.items()
try:
appstruct = myform.validate(controls)
except ValidationFailure, e:
return {'form':e.render(), 'values': False}
# Process the valid form data, do some work
values = {
"name": appstruct['name'],
"shoe_size": appstruct['shoe_size'],
}
return {"form": myform.render(), "values": values}
# We are a GET not a POST
return {"form": myform.render(), "values": None}
|
Copy the following into step02/templates/site_view.pt:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Projector</title>
<link rel="stylesheet" href="/deform_static/css/form.css"
type="text/css"
/>
<script type="text/javascript"
src="/deform_static/scripts/jquery-1.4.2.min.js"></script>
<script type="text/javascript"
src="/deform_static/scripts/deform.js"></script>
</head>
<body>
<h2>Hello Form</h2>
<div tal:content="structure form">form</div>
<p tal:condition="values">Valid form values: ${values.name} and
${values.shoe_size}.</p>
</body>
</html>
|
Copy the following into step02/tests.py:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | import unittest
from pyramid.testing import DummyRequest
class ProjectorViewsUnitTests(unittest.TestCase):
def _makeOne(self, request):
from views import ProjectorViews
inst = ProjectorViews(request)
return inst
def test_site_view(self):
request = DummyRequest()
inst = self._makeOne(request)
result = inst.site_view()
self.assertTrue('form' in result.keys())
class ProjectorFunctionalTests(unittest.TestCase):
def setUp(self):
from application import main
app = main()
from webtest import TestApp
self.testapp = TestApp(app)
def test_GET(self):
# Get the form
res = self.testapp.get('/', status=200)
self.assertTrue('Hello Form' in res.body)
|
$ nosetests should report running 2 tests.
$ python application.py
Open http://127.0.0.1:8080/ in your browser.
In this step we see the explicit branching in a self-posting form. This is important: it’s useful to have a common pattern to see which code path goes where, especially on a large project with lots of forms.
In many cases, this self-posting form isn’t going to return itself on success. Instead, it will redirect using pyramid.httpexceptions.HTTPFound to the newly-created resource.