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 |
|
|
34 |
#. First we copy the results of the ``view_classes`` step: |
|
35 |
|
|
36 |
.. code-block:: bash |
|
37 |
|
187104
|
38 |
$ cd ..; cp -r view_classes forms; cd forms |
b1b922
|
39 |
|
59c8fc
|
40 |
#. Let's edit ``forms/setup.py`` to declare a dependency on Deform (which then |
SP |
41 |
pulls in Colander as a dependency: |
b1b922
|
42 |
|
PE |
43 |
.. literalinclude:: forms/setup.py |
263ba4
|
44 |
:emphasize-lines: 4 |
b1b922
|
45 |
:linenos: |
PE |
46 |
|
|
47 |
#. We can now install our project in development mode: |
|
48 |
|
|
49 |
.. code-block:: bash |
|
50 |
|
9845f7
|
51 |
$ $VENV/bin/pip install -e . |
b1b922
|
52 |
|
59c8fc
|
53 |
#. Register a static view in ``forms/tutorial/__init__.py`` for Deform's CSS, |
SP |
54 |
JavaScript, etc., as well as our demo wiki page's views: |
b1b922
|
55 |
|
PE |
56 |
.. literalinclude:: forms/tutorial/__init__.py |
|
57 |
:linenos: |
|
58 |
|
59c8fc
|
59 |
#. Implement the new views, as well as the form schemas and some dummy data, in |
SP |
60 |
``forms/tutorial/views.py``: |
b1b922
|
61 |
|
PE |
62 |
.. literalinclude:: forms/tutorial/views.py |
|
63 |
:linenos: |
|
64 |
|
59c8fc
|
65 |
#. A template for the top of the "wiki" in ``forms/tutorial/wiki_view.pt``: |
b1b922
|
66 |
|
PE |
67 |
.. literalinclude:: forms/tutorial/wiki_view.pt |
|
68 |
:language: html |
|
69 |
:linenos: |
|
70 |
|
|
71 |
#. Another template for adding/editing in |
|
72 |
``forms/tutorial/wikipage_addedit.pt``: |
|
73 |
|
|
74 |
.. literalinclude:: forms/tutorial/wikipage_addedit.pt |
|
75 |
:language: html |
|
76 |
:linenos: |
|
77 |
|
0d37a9
|
78 |
#. Add a template at ``forms/tutorial/wikipage_view.pt`` for viewing a wiki |
SP |
79 |
page: |
b1b922
|
80 |
|
PE |
81 |
.. literalinclude:: forms/tutorial/wikipage_view.pt |
|
82 |
:language: html |
|
83 |
:linenos: |
59c8fc
|
84 |
|
0d37a9
|
85 |
#. Our tests in ``forms/tutorial/tests.py`` don't run, so let's modify them: |
SP |
86 |
|
|
87 |
.. literalinclude:: forms/tutorial/tests.py |
|
88 |
:linenos: |
|
89 |
|
59c8fc
|
90 |
#. Run the tests: |
SP |
91 |
|
|
92 |
.. code-block:: bash |
|
93 |
|
|
94 |
$ $VENV/bin/py.test tutorial/tests.py -q |
|
95 |
.. |
|
96 |
2 passed in 0.45 seconds |
b1b922
|
97 |
|
PE |
98 |
#. Run your Pyramid application with: |
|
99 |
|
|
100 |
.. code-block:: bash |
|
101 |
|
187104
|
102 |
$ $VENV/bin/pserve development.ini --reload |
b1b922
|
103 |
|
d749bf
|
104 |
#. Open http://localhost:6543/ in a browser. |
b1b922
|
105 |
|
PE |
106 |
|
|
107 |
Analysis |
|
108 |
======== |
|
109 |
|
59c8fc
|
110 |
This step helps illustrate the utility of asset specifications for static |
SP |
111 |
assets. We have an outside package called Deform with static assets which need |
|
112 |
to be published. We don't have to know where on disk it is located. We point at |
|
113 |
the package, then the path inside the package. |
b1b922
|
114 |
|
59c8fc
|
115 |
We just need to include a call to ``add_static_view`` to make that directory |
SP |
116 |
available at a URL. For Pyramid-specific packages, Pyramid provides a facility |
|
117 |
(``config.include()``) which even makes that unnecessary for consumers of a |
|
118 |
package. (Deform is not specific to Pyramid.) |
b1b922
|
119 |
|
59c8fc
|
120 |
Our forms have rich widgets which need the static CSS and JavaScript just |
SP |
121 |
mentioned. Deform has a :term:`resource registry` which allows widgets to |
|
122 |
specify which JavaScript and CSS are needed. Our ``wikipage_addedit.pt`` |
|
123 |
template shows how we iterated over that data to generate markup that includes |
|
124 |
the needed resources. |
b1b922
|
125 |
|
59c8fc
|
126 |
Our add and edit views use a pattern called *self-posting forms*. Meaning, the |
SP |
127 |
same URL is used to ``GET`` the form as is used to ``POST`` the form. The |
|
128 |
route, the view, and the template are the same URL whether you are walking up |
|
129 |
to it for the first time or you clicked a button. |
b1b922
|
130 |
|
59c8fc
|
131 |
Inside the view we do ``if 'submit' in self.request.params:`` to see if this |
SP |
132 |
form was a ``POST`` where the user clicked on a particular button |
b1b922
|
133 |
``<input name="submit">``. |
PE |
134 |
|
|
135 |
The form controller then follows a typical pattern: |
|
136 |
|
59c8fc
|
137 |
- If you are doing a ``GET``, skip over and just return the form. |
b1b922
|
138 |
|
59c8fc
|
139 |
- If you are doing a ``POST``, validate the form contents. |
b1b922
|
140 |
|
59c8fc
|
141 |
- If the form is invalid, bail out by re-rendering the form with the supplied |
SP |
142 |
``POST`` data. |
b1b922
|
143 |
|
59c8fc
|
144 |
- If the validation succeeded, perform some action and issue a redirect via |
SP |
145 |
``HTTPFound``. |
b1b922
|
146 |
|
59c8fc
|
147 |
We are, in essence, writing our own form controller. Other Pyramid-based |
SP |
148 |
systems, including ``pyramid_deform``, provide a form-centric view class which |
|
149 |
automates much of this branching and routing. |
b1b922
|
150 |
|
59c8fc
|
151 |
|
SP |
152 |
Extra credit |
b1b922
|
153 |
============ |
PE |
154 |
|
59c8fc
|
155 |
#. Give a try at a button that goes to a delete view for a particular wiki |
SP |
156 |
page. |