Step 01: Hello World with Deform

Many times you want forms generated for you. If you can live within the constraints, you gain a lot: slick widgets, automatic layout, validation, add and edit handling, and even Ajax submission.

Deform is a part of a set of Pylons libraries that break this functionality into its logically-separate parts:

  • Peppercorn for marshalling form data from requests
  • Colander for expressing constraints and fields as schemas
  • Deform for generating HTML form markup from a Colander schema, with built-in widgets and support for custom widgets

In this step we do the smallest possible step with Deform and Colander.

Goals

  • Hello world using Deform and Colander

Objectives

  • Add a static view for Deform’s static resources
  • Include those resources (CSS, JS) in the template’s <head>
  • Define a basic schema

Steps

  1. easy_install deform

  2. $ cd ../../forms_schema; mkdir step01; cd step01

  3. Copy the following into step01/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()
    
  4. Copy the following into step01/views.py:

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    import colander
    from deform import Form
    from pyramid.view import view_config
    
    class Person(colander.MappingSchema):
        name = colander.SchemaNode(colander.String())
    
    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',))
    
            return {"form": myform.render()}
    
  5. Copy the following into step01/templates/site_view.pt:

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    <!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>
    </body>
    </html>
    
  6. Copy the following into step01/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
    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_it(self):
            res = self.testapp.get('/', status=200)
            self.assertTrue('Hello Form' in res.body)
    
  7. $ nosetests should report running 2 tests.

  8. $ python application.py

  9. Open http://127.0.0.1:8080/ in your browser.

Extra Credit

  1. Read the Colander docs and allow the name field to be optionally missing without raising an validation warning.
  2. Add an integer field.

Analysis

The application.py added a static view to the configuration for deform_static.

There is no real form hanlding being done. However, the form does do validation.

Discussion

  • Previous attempts at forms, and other form packages comparison and contrast
  • Reminder: Every choice on form libraries is doomed
  • Other ways to “discover” the path to the static views for deform

Table Of Contents