Steve Piercy
2018-10-09 05915720f97df868e0b7dcff6e9b8eed964b8a90
commit | author | age
b731b5 1 .. _qtut_forms:
PE 2
b1b922 3 ====================================
ab0319 4 18: Forms and Validation with Deform
b1b922 5 ====================================
PE 6
7 Schema-driven, autogenerated forms with validation.
8
59c8fc 9
b1b922 10 Background
PE 11 ==========
12
59c8fc 13 Modern web applications deal extensively with forms. Developers, though, have a
SP 14 wide range of philosophies about how frameworks should help them with their
15 forms. As such, Pyramid doesn't directly bundle one particular form library.
16 Instead there are a variety of form libraries that are easy to use in Pyramid.
b1b922 17
59c8fc 18 :ref:`Deform <deform:overview>` is one such library. In this step, we introduce
SP 19 Deform for our forms. This also gives us :ref:`Colander <colander:overview>`
003b9a 20 for schemas and validation.
59c8fc 21
b1b922 22
PE 23 Objectives
24 ==========
25
59c8fc 26 - Make a schema using Colander, the companion to Deform.
b1b922 27
59c8fc 28 - Create a form with Deform and change our views to handle validation.
SP 29
b1b922 30
PE 31 Steps
32 =====
33
42aa12 34 #.  First we copy the results of the ``view_classes`` step:
b1b922 35
42aa12 36     .. code-block:: bash
b1b922 37
42aa12 38         cd ..; cp -r view_classes forms; cd forms
b1b922 39
42aa12 40 #.  Let's edit ``forms/setup.py`` to declare a dependency on Deform, which in turn pulls in Colander as a dependency:
b1b922 41
42aa12 42     .. literalinclude:: forms/setup.py
e73977 43         :emphasize-lines: 6
42aa12 44         :linenos:
b1b922 45
42aa12 46 #.  We can now install our project in development mode:
b1b922 47
42aa12 48     .. code-block:: bash
b1b922 49
42aa12 50         $VENV/bin/pip install -e .
b1b922 51
42aa12 52 #.  Register a static view in ``forms/tutorial/__init__.py`` for Deform's CSS, JavaScript, etc., as well as our demo wiki page's views:
b1b922 53
42aa12 54     .. literalinclude:: forms/tutorial/__init__.py
SP 55         :linenos:
b1b922 56
42aa12 57 #.  Implement the new views, as well as the form schemas and some dummy data, in ``forms/tutorial/views.py``:
b1b922 58
42aa12 59     .. literalinclude:: forms/tutorial/views.py
SP 60         :linenos:
b1b922 61
42aa12 62 #.  A template for the top of the "wiki" in ``forms/tutorial/wiki_view.pt``:
b1b922 63
42aa12 64     .. literalinclude:: forms/tutorial/wiki_view.pt
SP 65         :language: html
66         :linenos:
b1b922 67
42aa12 68 #.  Another template for adding/editing in ``forms/tutorial/wikipage_addedit.pt``:
b1b922 69
42aa12 70     .. literalinclude:: forms/tutorial/wikipage_addedit.pt
SP 71         :language: html
72         :linenos:
b1b922 73
42aa12 74 #.  Add a template at ``forms/tutorial/wikipage_view.pt`` for viewing a wiki page:
b1b922 75
42aa12 76     .. literalinclude:: forms/tutorial/wikipage_view.pt
SP 77         :language: html
78         :linenos:
59c8fc 79
42aa12 80 #.  Our tests in ``forms/tutorial/tests.py`` don't run, so let's modify them:
0d37a9 81
42aa12 82     .. literalinclude:: forms/tutorial/tests.py
SP 83         :linenos:
0d37a9 84
42aa12 85 #.  Run the tests:
59c8fc 86
42aa12 87     .. code-block:: bash
59c8fc 88
42aa12 89         $VENV/bin/pytest tutorial/tests.py -q
SP 90         ..
91         6 passed in 0.81 seconds
b1b922 92
42aa12 93 #.  Run your Pyramid application with:
b1b922 94
42aa12 95     .. code-block:: bash
b1b922 96
42aa12 97         $VENV/bin/pserve development.ini --reload
b1b922 98
42aa12 99 #.  Open http://localhost:6543/ in a browser.
b1b922 100
PE 101
102 Analysis
103 ========
104
59c8fc 105 This step helps illustrate the utility of asset specifications for static
SP 106 assets. We have an outside package called Deform with static assets which need
107 to be published. We don't have to know where on disk it is located. We point at
108 the package, then the path inside the package.
b1b922 109
59c8fc 110 We just need to include a call to ``add_static_view`` to make that directory
SP 111 available at a URL. For Pyramid-specific packages, Pyramid provides a facility
112 (``config.include()``) which even makes that unnecessary for consumers of a
113 package. (Deform is not specific to Pyramid.)
b1b922 114
59c8fc 115 Our forms have rich widgets which need the static CSS and JavaScript just
SP 116 mentioned. Deform has a :term:`resource registry` which allows widgets to
117 specify which JavaScript and CSS are needed. Our ``wikipage_addedit.pt``
118 template shows how we iterated over that data to generate markup that includes
119 the needed resources.
b1b922 120
59c8fc 121 Our add and edit views use a pattern called *self-posting forms*. Meaning, the
SP 122 same URL is used to ``GET`` the form as is used to ``POST`` the form. The
123 route, the view, and the template are the same URL whether you are walking up
124 to it for the first time or you clicked a button.
b1b922 125
59c8fc 126 Inside the view we do ``if 'submit' in self.request.params:`` to see if this
SP 127 form was a ``POST`` where the user clicked on a particular button
b1b922 128 ``<input name="submit">``.
PE 129
130 The form controller then follows a typical pattern:
131
59c8fc 132 - If you are doing a ``GET``, skip over and just return the form.
b1b922 133
59c8fc 134 - If you are doing a ``POST``, validate the form contents.
b1b922 135
59c8fc 136 - If the form is invalid, bail out by re-rendering the form with the supplied
SP 137   ``POST`` data.
b1b922 138
59c8fc 139 - If the validation succeeded, perform some action and issue a redirect via
SP 140   ``HTTPFound``.
b1b922 141
59c8fc 142 We are, in essence, writing our own form controller. Other Pyramid-based
SP 143 systems, including ``pyramid_deform``, provide a form-centric view class which
144 automates much of this branching and routing.
b1b922 145
59c8fc 146
SP 147 Extra credit
b1b922 148 ============
PE 149
59c8fc 150 #. Give a try at a button that goes to a delete view for a particular wiki
SP 151    page.