Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 509 lines (385 sloc) 18.923 kb
bdbe41d @mcdonc Remove most schema-related APIs in order to make the task of document…
mcdonc authored
1 Basic Usage
2 ===========
3
4 In this chapter, we'll walk through basic usage of Deform to render a
5 form, and capture and validate input.
6
4c7aa96 @mcdonc More basics.
mcdonc authored
7 The steps a developer must take to cause a form to be renderered and
bdbe41d @mcdonc Remove most schema-related APIs in order to make the task of document…
mcdonc authored
8 subsequently be ready to accept form submission input are:
9
10 - Define a schema
11
12 - Create a form object.
13
14 - Assign non-default widgets to fields in the form (optional).
15
16 - Render the form.
17
18 Once the form is rendered, a user will interact with the form in his
375338e @mcdonc More basic docs.
mcdonc authored
19 browser, and some point, he will submit it. When the user submits the
20 form, the data provided by the user will either validate properly, or
21 the form will need to be rerendered with error markers which help to
22 inform the user of which parts need to be filled in "properly" (as
ba6c0f3 @cjw296 typo
cjw296 authored
23 defined by the schema). We allow the user to continue filling in the
375338e @mcdonc More basic docs.
mcdonc authored
24 form, submitting, and revalidating indefinitely.
bdbe41d @mcdonc Remove most schema-related APIs in order to make the task of document…
mcdonc authored
25
4c7aa96 @mcdonc More basics.
mcdonc authored
26 Defining A Schema
27 -----------------
bdbe41d @mcdonc Remove most schema-related APIs in order to make the task of document…
mcdonc authored
28
29 The first step to using Deform is to create a :term:`schema` which
30 represents the data structure you wish to be captured via a form
4c7aa96 @mcdonc More basics.
mcdonc authored
31 rendering.
bdbe41d @mcdonc Remove most schema-related APIs in order to make the task of document…
mcdonc authored
32
33 For example, let's imagine you want to create a form based roughly on
34 a data structure you'll obtain by reading data from a relational
35 database. An example of such a data structure might look something
36 like this:
37
38 .. code-block:: python
39 :linenos:
40
41 [
42 {
43 'name':'keith',
44 'age':20,
45 },
46 {
47 'name':'fred',
48 'age':23,
49 },
50 ]
51
52 In other words, the database query we make returns a sequence of
53 *people*; each person is represented by some data. We need to edit
54 this data. There won't be many people in this list, so we don't need
55 any sort of paging or batching to make our way through the list; we
56 can display it all on one form page.
57
eac2d3e @reedobrien minor blue pencil
reedobrien authored
58 Deform designates a structure akin to the example above as an
bdbe41d @mcdonc Remove most schema-related APIs in order to make the task of document…
mcdonc authored
59 :term:`appstruct`. The term "appstruct" is shorthand for "application
60 structure", because it's the kind of high-level structure that an
61 application usually cares about: the data present in an appstruct is
62 useful directly to an application itself.
63
64 .. note:: An appstruct differs from other structures that Deform uses
65 (such as :term:`pstruct` and :term:`cstruct` structures): pstructs
66 and cstructs are typically only useful during intermediate parts of
67 the rendering process.
68
563cd28 @mcdonc Move stuff around.
mcdonc authored
69 Usually, given some appstruct, you can divine a :term:`schema` that
70 would allow you to edit the data related to the appstruct. Let's
71 define a schema which will attempt to serialize this particular
72 appstruct to a form. Our application has these requirements of the
73 resulting form:
bdbe41d @mcdonc Remove most schema-related APIs in order to make the task of document…
mcdonc authored
74
f457c9d @mcdonc iYup.
mcdonc authored
75 - It must be possible to add and remove a person.
bdbe41d @mcdonc Remove most schema-related APIs in order to make the task of document…
mcdonc authored
76
f457c9d @mcdonc iYup.
mcdonc authored
77 - It must be possible to change any person's name or age after they've
78 been added.
bdbe41d @mcdonc Remove most schema-related APIs in order to make the task of document…
mcdonc authored
79
80 Here's a schema that will help us meet those requirements:
81
82 .. code-block:: python
83 :linenos:
84
85 import colander
86
87 class Person(colander.MappingSchema):
88 name = colander.SchemaNode(colander.String())
375338e @mcdonc More basic docs.
mcdonc authored
89 age = colander.SchemaNode(colander.Integer(),
bdbe41d @mcdonc Remove most schema-related APIs in order to make the task of document…
mcdonc authored
90 validator=colander.Range(0, 200))
91
92 class People(colander.SequenceSchema):
93 person = Person()
94
375338e @mcdonc More basic docs.
mcdonc authored
95 class Schema(colander.MappingSchema):
96 people = People()
97
98 schema = Schema()
bdbe41d @mcdonc Remove most schema-related APIs in order to make the task of document…
mcdonc authored
99
7b8a521 @mcdonc - Moved to GitHub (https://github.com/Pylons/deform).
mcdonc authored
100 The schemas used by Deform come from a package named :term:`Colander`. The
101 canonical documentation for Colander exists at
211f599 @mcdonc fix colander links
mcdonc authored
102 http://docs.pylonsproject.org/projects/colander/dev/ . To compose complex
103 schemas, you'll need to read it to get comfy with the documentation of the
104 default Colander data types. But for now, we can play it by ear.
4c7aa96 @mcdonc More basics.
mcdonc authored
105
375338e @mcdonc More basic docs.
mcdonc authored
106 For ease of reading, we've actually defined *three* schemas above, but
107 we coalesce them all into a single schema instance as ``schema`` in
108 the last step. A ``People`` schema is a collection of ``Person``
109 schema nodes. As the result of our definitions, a ``Person``
110 represents:
bdbe41d @mcdonc Remove most schema-related APIs in order to make the task of document…
mcdonc authored
111
112 - A ``name``, which must be a string.
113
114 - An ``age``, which must be deserializable to an integer; after
115 deserialization happens, a validator ensures that the integer is
116 between 0 and 200 inclusive.
117
118 Schema Node Objects
119 ~~~~~~~~~~~~~~~~~~~
120
375338e @mcdonc More basic docs.
mcdonc authored
121 .. note:: This section repeats and contextualizes the :term:`Colander`
122 documentation about schema nodes in order to prevent you from
123 needing to switch away from this page to another while trying to
124 learn about forms. But you can also get much the same information
211f599 @mcdonc fix colander links
mcdonc authored
125 at http://docs.pylonsproject.org/projects/colander/dev/
4c7aa96 @mcdonc More basics.
mcdonc authored
126
d62c42f @cjw296 doc changes for the addition of preparers to colander
cjw296 authored
127 A schema is composed of one or more *schema node* objects, each typically of
128 the class :class:`colander.SchemaNode`, usually in a nested arrangement.
129 Each schema node object has a required *type*, an optional *preparer*
130 for adjusting data after deserialization, an optional
131 *validator* for deserialized prepared data, an optional *default*, an
04a6cce @mcdonc revert css-on-field-classes changeset, sorry @sweh, it doesnt make se…
mcdonc authored
132 optional *missing*, an optional *title*, an optional *description*,
133 and a slightly less optional *name*. It also accepts *arbitrary*
134 keyword arguments, which are attached directly as attributes to the
d62c42f @cjw296 doc changes for the addition of preparers to colander
cjw296 authored
135 node instance.
bdbe41d @mcdonc Remove most schema-related APIs in order to make the task of document…
mcdonc authored
136
137 The *type* of a schema node indicates its data type (such as
138 :class:`colander.Int` or :class:`colander.String`).
139
d62c42f @cjw296 doc changes for the addition of preparers to colander
cjw296 authored
140 The *preparer* of a schema node is called after
141 deserialization but before validation; it prepares a deserialized
142 value for validation. Examples would be to prepend schemes that may be
143 missing on url values or to filter html provided by a rich text
144 editor. A preparer is not called during serialization, only during
145 deserialization.
146
147 The *validator* of a schema node is called after deserialization and
148 preparation ; it makes sure the value matches a constraint. An example of
bdbe41d @mcdonc Remove most schema-related APIs in order to make the task of document…
mcdonc authored
149 such a validator is provided in the schema above:
150 ``validator=colander.Range(0, 200)``. A validator is not called after
4c7aa96 @mcdonc More basics.
mcdonc authored
151 schema node serialization, only after node deserialization.
bdbe41d @mcdonc Remove most schema-related APIs in order to make the task of document…
mcdonc authored
152
295fcd7 @mcdonc update docs
mcdonc authored
153 The *default* of a schema node indicates the value to be serialized if
154 a value for the schema node is not found in the input data during
3802a82 @mcdonc fix misstatements
mcdonc authored
155 serialization. It should be the deserialized representation.
295fcd7 @mcdonc update docs
mcdonc authored
156
157 The *missing* of a schema node indicates the value to be deserialized
158 if a value for the schema node is not found in the input data during
159 deserialization. It should be the deserialized representation. If a
3802a82 @mcdonc fix misstatements
mcdonc authored
160 schema node does not have a ``missing`` value, a
161 :exc:`colander.Invalid` exception will be raised if the data structure
162 being deserialized does not contain a matching value.
bdbe41d @mcdonc Remove most schema-related APIs in order to make the task of document…
mcdonc authored
163
164 The *name* of a schema node is used to relate schema nodes to each
165 other. It is also used as the title if a title is not provided.
166
167 The *title* of a schema node is metadata about a schema node. It
4c7aa96 @mcdonc More basics.
mcdonc authored
168 shows up in the legend above the form field(s) related to the schema
bdbe41d @mcdonc Remove most schema-related APIs in order to make the task of document…
mcdonc authored
169 node. By default, it is a capitalization of the *name*.
170
171 The *description* of a schema node is metadata about a schema node.
e7afd0a @mcdonc expand
mcdonc authored
172 It shows up as a tooltip when someone hovers over the form control(s)
173 related to a :term:`field`. By default, it is empty.
bdbe41d @mcdonc Remove most schema-related APIs in order to make the task of document…
mcdonc authored
174
175 The name of a schema node that is introduced as a class-level
176 attribute of a :class:`colander.MappingSchema`,
177 :class:`colander.TupleSchema` or a :class:`colander.SequenceSchema` is
178 its class attribute name. For example:
179
180 .. code-block:: python
181 :linenos:
182
183 import colander
184
185 class Phone(colander.MappingSchema):
186 location = colander.SchemaNode(colander.String(),
187 validator=colander.OneOf(['home','work']))
188 number = colander.SchemaNode(colander.String())
189
190 The name of the schema node defined via ``location =
191 colander.SchemaNode(..)`` within the schema above is ``location``.
192 The title of the same schema node is ``Location``.
193
194 Schema Objects
195 ~~~~~~~~~~~~~~
196
197 In the examples above, if you've been paying attention, you'll have
198 noticed that we're defining classes which subclass from
199 :class:`colander.MappingSchema`, and :class:`colander.SequenceSchema`.
200 It's turtles all the way down: the result of creating an instance of
375338e @mcdonc More basic docs.
mcdonc authored
201 any of :class:`colander.MappingSchema`, :class:`colander.TupleSchema`
202 or :class:`colander.SequenceSchema` object is *also* a
bdbe41d @mcdonc Remove most schema-related APIs in order to make the task of document…
mcdonc authored
203 :class:`colander.SchemaNode` object.
204
205 Instantiating a :class:`colander.MappingSchema` creates a schema node
206 which has a *type* value of :class:`colander.Mapping`.
207
208 Instantiating a :class:`colander.TupleSchema` creates a schema node
209 which has a *type* value of :class:`colander.Tuple`.
210
211 Instantiating a :class:`colander.SequenceSchema` creates a schema node
212 which has a *type* value of :class:`colander.Sequence`.
213
4c7aa96 @mcdonc More basics.
mcdonc authored
214 Creating Schemas Without Using a Class Statement (Imperatively)
215 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
216
7b8a521 @mcdonc - Moved to GitHub (https://github.com/Pylons/deform).
mcdonc authored
217 See
ac9eaea @davidjb Minor documentation updates: link + RichTextWidget
davidjb authored
218 http://docs.pylonsproject.org/projects/colander/dev/basics.html#defining-a-schema-imperatively
375338e @mcdonc More basic docs.
mcdonc authored
219 for information about how to create schemas without using a ``class``
220 statement.
221
222 Creating a schema with or without ``class`` statements is purely a
223 style decision; the outcome of creating a schema without ``class``
224 statements is the same as creating one with ``class`` statements.
4c7aa96 @mcdonc More basics.
mcdonc authored
225
bdc9760 @cjw296 split stuff that isn't basic usage into its own chapter and edit
cjw296 authored
226 Rendering a Form
227 ----------------
bdbe41d @mcdonc Remove most schema-related APIs in order to make the task of document…
mcdonc authored
228
229 Earlier we defined a schema:
230
231 .. code-block:: python
232 :linenos:
233
234 import colander
235
236 class Person(colander.MappingSchema):
237 name = colander.SchemaNode(colander.String())
375338e @mcdonc More basic docs.
mcdonc authored
238 age = colander.SchemaNode(colander.Integer(),
bdbe41d @mcdonc Remove most schema-related APIs in order to make the task of document…
mcdonc authored
239 validator=colander.Range(0, 200))
240
241 class People(colander.SequenceSchema):
242 person = Person()
243
375338e @mcdonc More basic docs.
mcdonc authored
244 class Schema(colander.MappingSchema):
245 people = People()
bdbe41d @mcdonc Remove most schema-related APIs in order to make the task of document…
mcdonc authored
246
375338e @mcdonc More basic docs.
mcdonc authored
247 schema = Schema()
bdbe41d @mcdonc Remove most schema-related APIs in order to make the task of document…
mcdonc authored
248
375338e @mcdonc More basic docs.
mcdonc authored
249 Let's now use this schema to create, render and validate a form.
bdbe41d @mcdonc Remove most schema-related APIs in order to make the task of document…
mcdonc authored
250
a63045d @mcdonc - The ``deform.Form`` class now accepts two extra keyword arguments in
mcdonc authored
251 .. _creating_a_form:
252
375338e @mcdonc More basic docs.
mcdonc authored
253 Creating a Form Object
254 ~~~~~~~~~~~~~~~~~~~~~~
bdbe41d @mcdonc Remove most schema-related APIs in order to make the task of document…
mcdonc authored
255
4c7aa96 @mcdonc More basics.
mcdonc authored
256 To create a form object, we do this:
bdbe41d @mcdonc Remove most schema-related APIs in order to make the task of document…
mcdonc authored
257
258 .. code-block:: python
259 :linenos:
260
4c7aa96 @mcdonc More basics.
mcdonc authored
261 from deform import Form
262 myform = Form(schema, buttons=('submit',))
263
375338e @mcdonc More basic docs.
mcdonc authored
264 We used the ``schema`` object (an instance of
265 :class:`colander.MappingSchema`) we created in the previous section as
266 the first positional parameter to the :class:`deform.Form` class; we
30505a6 @mcdonc iYup.
mcdonc authored
267 passed the value ``('submit',)`` as the value of the ``buttons``
717b984 @mcdonc expand widget docs
mcdonc authored
268 keyword argument. This will cause a single ``submit`` input element
269 labeled ``Submit`` to be injected at the bottom of the form rendering.
270 We chose to pass in the button names as a sequence of strings, but we
271 could have also passed a sequence of instances of the
272 :class:`deform.Button` class. Either is permissible.
375338e @mcdonc More basic docs.
mcdonc authored
273
274 Note that the first positional argument to :class:`deform.Form` must
275 be a schema node representing a *mapping* object (a structure which
276 maps a key to a value). We satisfied this constraint above by passing
277 our ``schema`` object, which we obtained via the
278 :class:`colander.MappingSchema` constructor, as the ``schema``
279 argument to the :class:`deform.Form` constructor
280
281 Although different kinds of schema nodes can be present in a schema
282 used by a Deform :class:`deform.Form` instance, a form instance cannot
283 deal with a schema node representing a sequence, a tuple schema, a
3802a82 @mcdonc fix misstatements
mcdonc authored
284 string, an integer, etc. as the value of its ``schema`` parameter;
285 only a schema node representing a mapping is permissible. This
286 typically means that the object passed as the ``schema`` argument to a
287 :class:`deform.Form` constructor must be obtained as the result of
288 using the :class:`colander.MappingSchema` constructor (or the
289 equivalent imperative spelling).
375338e @mcdonc More basic docs.
mcdonc authored
290
4c7aa96 @mcdonc More basics.
mcdonc authored
291 Rendering the Form
292 ~~~~~~~~~~~~~~~~~~
293
375338e @mcdonc More basic docs.
mcdonc authored
294 Once we've created a Form object, we can render it without issue by
295 calling the :meth:`deform.Field.render` method: the
296 :class:`deform.Form` class is a subclass of the :class:`deform.Field`
297 class, so this method is available to a :class:`deform.Form` instance.
298
172d5fe Document rewrite (Basics Section)
Josh Finnie authored
299 If we wanted to render an "add" form (a form without initial
300 data), we'd just omit the appstruct while calling
301 :meth:`deform.Field.render`.
302
303 .. code-block:: python
304
305 form = myform.render()
306
375338e @mcdonc More basic docs.
mcdonc authored
307 If we have some existing data already that we'd like to edit using the
308 form (the form is an "edit form" as opposed to an "add form"). That
309 data might look like this:
310
311 .. code-block:: python
312 :linenos:
313
314 appstruct = [
315 {
316 'name':'keith',
317 'age':20,
318 },
319 {
320 'name':'fred',
321 'age':23,
322 },
323 ]
324
325 To inject it into the serialized form as the data to be edited, we'd
326 pass it in to the :meth:`deform.Field.render` method to get a form
327 rendering:
328
329 .. code-block:: python
330
331 form = myform.render(appstruct)
332
172d5fe Document rewrite (Basics Section)
Josh Finnie authored
333 If, finally, instead we wanted to render a "read-only" variant of an edit form
375338e @mcdonc More basic docs.
mcdonc authored
334 using the same appstruct, we'd pass the ``readonly`` flag as ``True``
335 to the :meth:`deform.Field.render` method.
336
337 .. code-block:: python
338
339 form = myform.render(appstruct, readonly=True)
340
341 This would cause a page to be rendered in a crude form without any
342 form controls, so the user it's presented to cannot edit it.
343
344 Once any of the above statements runs, the ``form`` variable is now a
345 Unicode object containing an HTML rendering of the edit form, useful
346 for serving out to a browser. The root tag of the rendering will be
347 the ``<form>`` tag representing this form (or at least a ``<div>`` tag
4c7aa96 @mcdonc More basics.
mcdonc authored
348 that contains this form tag), so the application using it will need to
349 wrap it in HTML ``<html>`` and ``<body>`` tags as necessary. It will
350 need to be inserted as "structure" without any HTML escaping.
351
a5c1205 @cjw296 fix broken sphinx links, not sure if all of these are correct :-S
cjw296 authored
352 .. _serving_up_the_rendered_form:
353
375338e @mcdonc More basic docs.
mcdonc authored
354 Serving up the Rendered Form
355 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
356
357 We now have an HTML rendering of a form as the variable named
358 ``form``. But before we can serve it up successfully to a browser
359 user, we have to make sure that static resources used by Deform can be
360 resolved properly. Some Deform widgets (including at least one we've
361 implied in our sample schema) require access to static resources such
362 as images via HTTP.
363
364 For these widgets to work properly, we'll need to arrange that files
365 in the directory named ``static`` within the :mod:`deform` package can
366 be resolved via a URL which lives at the same hostname and port number
367 as the page which serves up the form itself. For example, the URL
24bda3f @davidjb Updating doco on static resource serving
davidjb authored
368 ``/static/css/form.css`` should be willing to return the
369 ``form.css`` CSS file in the ``static/css`` directory in the
370 :mod:`deform` package as ``text/css`` content and return
371 ``/static/scripts/deform.js`` as``text/javascript`` content.
372 How you arrange to do this is dependent on
4dba08c @multani Fix references to repoze.bfg and update obsoletes URLs in the demo ap…
multani authored
373 your web framework. It's done in :mod:`pyramid` imperative
4c7aa96 @mcdonc More basics.
mcdonc authored
374 configuration via:
bdbe41d @mcdonc Remove most schema-related APIs in order to make the task of document…
mcdonc authored
375
376 .. code-block:: python
377
4c7aa96 @mcdonc More basics.
mcdonc authored
378 config = Configurator(...)
379 ...
380 config.add_static_view('static', 'deform:static')
381 ...
bdbe41d @mcdonc Remove most schema-related APIs in order to make the task of document…
mcdonc authored
382
75651cb @mcdonc Bug Fixes
mcdonc authored
383 Your web framework will use a different mechanism to offer up static
384 files.
385
c6a1021 @mcdonc Documentation goalline nearing.
mcdonc authored
386 Some of the more important files in the set of JavaScript, CSS files,
387 and images present in the ``static`` directory of the :mod:`deform`
388 package are the following:
389
4a79a6d @tsauerwein Fix jQuery version in docs
tsauerwein authored
390 ``static/scripts/jquery-2.0.3.min.js``
c6a1021 @mcdonc Documentation goalline nearing.
mcdonc authored
391 A local copy of the JQuery javascript library, used by widgets and
392 other JavaScript files.
393
394 ``static/scripts/deform.js``
395 A JavaScript library which should be loaded by any template which
396 injects a rendered Deform form.
397
398 ``static/css/form.css``
399 CSS related to form element renderings.
400
401 Each of these libraries should be included in the ``<head>`` tag of a
402 page which renders a Deform form, e.g.:
403
404 .. code-block:: xml
405 :linenos:
406
407 <head>
408 <title>
409 Deform Demo Site
410 </title>
411 <!-- Meta Tags -->
412 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
413 <!-- CSS -->
414 <link rel="stylesheet" href="/static/css/form.css" type="text/css" />
415 <!-- JavaScript -->
416 <script type="text/javascript"
4a79a6d @tsauerwein Fix jQuery version in docs
tsauerwein authored
417 src="/static/scripts/jquery-2.0.3.min.js"></script>
c6a1021 @mcdonc Documentation goalline nearing.
mcdonc authored
418 <script type="text/javascript"
419 src="/static/scripts/deform.js"></script>
420 </head>
421
75651cb @mcdonc Bug Fixes
mcdonc authored
422 The :meth:`deform.field.get_widget_resources` method can be used to
423 tell you which ``static`` directory-relative files are required by a
424 particular form rendering, so that you can inject only the ones
425 necessary into the page rendering.
426
427 The JavaScript function ``deform.load()`` *must* be called by the HTML
428 page (usually in a script tag near the end of the page, ala
429 ``<script..>deform.load()</script>``) which renders a Deform form in
430 order for widgets which use JavaScript to do proper event and behavior
431 binding. If this function is not called, built-in widgets which use
432 JavaScript will not function properly. For example, you might include
433 this within the body of the rendered page near its end:
434
435 .. code-block:: xml
436 :linenos:
437
438 <script type="text/javascript">
439 deform.load()
440 </script>
441
c6a1021 @mcdonc Documentation goalline nearing.
mcdonc authored
442 As above, the head should also contain a ``<meta>`` tag which names a
443 ``utf-8`` charset in a ``Content-Type`` http-equiv. This is a sane
444 setting for most systems.
445
4c7aa96 @mcdonc More basics.
mcdonc authored
446 Validating a Form Submission
bdc9760 @cjw296 split stuff that isn't basic usage into its own chapter and edit
cjw296 authored
447 ----------------------------
bdbe41d @mcdonc Remove most schema-related APIs in order to make the task of document…
mcdonc authored
448
375338e @mcdonc More basic docs.
mcdonc authored
449 Once the user seen the form and has chewed on its inputs a bit, he
450 will eventually submit the form. When he submits it, the logic you
451 use to deal with the form validation must do a few things:
bdbe41d @mcdonc Remove most schema-related APIs in order to make the task of document…
mcdonc authored
452
4c7aa96 @mcdonc More basics.
mcdonc authored
453 - It must detect that a submit button was clicked.
bdbe41d @mcdonc Remove most schema-related APIs in order to make the task of document…
mcdonc authored
454
4c7aa96 @mcdonc More basics.
mcdonc authored
455 - It must obtain the list of :term:`form controls` from the form POST
456 data.
bdbe41d @mcdonc Remove most schema-related APIs in order to make the task of document…
mcdonc authored
457
4c7aa96 @mcdonc More basics.
mcdonc authored
458 - It must call the :meth:`deform.Form.validate` method with the list
459 of form controls.
bdbe41d @mcdonc Remove most schema-related APIs in order to make the task of document…
mcdonc authored
460
5e63b2b @dnouri The exception's called ValidationFailure not Error, as in the example
dnouri authored
461 - It must be willing to catch a :exc:`deform.ValidationFailure`
4c7aa96 @mcdonc More basics.
mcdonc authored
462 exception and rerender the form if there were validation errors.
bdbe41d @mcdonc Remove most schema-related APIs in order to make the task of document…
mcdonc authored
463
4c7aa96 @mcdonc More basics.
mcdonc authored
464 For example, using the :term:`WebOb` API for the above tasks, and the
465 ``form`` object we created earlier, such a dance might look like this:
bdbe41d @mcdonc Remove most schema-related APIs in order to make the task of document…
mcdonc authored
466
467 .. code-block:: python
468 :linenos:
469
375338e @mcdonc More basic docs.
mcdonc authored
470 if 'submit' in request.POST: # detect that the submit button was clicked
471
472 controls = request.POST.items() # get the form controls
473
474 try:
475 appstruct = myform.validate(controls) # call validate
476 except ValidationFailure, e: # catch the exception
477 return {'form':e.render()} # re-render the form with an exception
478
479 # the form submission succeeded, we have the data
480 return {'form':None, 'appstruct':appstruct}
bdbe41d @mcdonc Remove most schema-related APIs in order to make the task of document…
mcdonc authored
481
4c7aa96 @mcdonc More basics.
mcdonc authored
482 The above set of statements is the sort of logic every web app that
483 uses Deform must do. If the validation stage does not fail, a
484 variable named ``appstruct`` will exist with the data serialized from
485 the form to be used in your application. Otherwise the form will be
486 rerendered.
bdbe41d @mcdonc Remove most schema-related APIs in order to make the task of document…
mcdonc authored
487
375338e @mcdonc More basic docs.
mcdonc authored
488 Note that by default, when any form submit button is clicked, the form
489 will send a post request to the same URL which rendered the form.
490 This can be changed by passing a different ``action`` to the
491 :class:`deform.Form` constructor.
492
493 Seeing it In Action
bdc9760 @cjw296 split stuff that isn't basic usage into its own chapter and edit
cjw296 authored
494 -------------------
375338e @mcdonc More basic docs.
mcdonc authored
495
496 To see an "add form" in action that follows the schema in this
3cef845 @tisdall deformdemo links to deform2demo
tisdall authored
497 chapter, visit `http://deform2demo.repoze.org/sequence_of_mappings/
498 <http://deform2demo.repoze.org/sequence_of_mappings/>`_.
375338e @mcdonc More basic docs.
mcdonc authored
499
500 To see a "readonly edit form" in action that follows the schema in
3b3c929 @mcdonc
mcdonc authored
501 this chapter, visit
3cef845 @tisdall deformdemo links to deform2demo
tisdall authored
502 `http://deform2demo.repoze.org/readonly_sequence_of_mappings/
503 <http://deform2demo.repoze.org/readonly_sequence_of_mappings/>`_
375338e @mcdonc More basic docs.
mcdonc authored
504
3cef845 @tisdall deformdemo links to deform2demo
tisdall authored
505 The application at http://deform2demo.repoze.org is a :mod:`pyramid`
375338e @mcdonc More basic docs.
mcdonc authored
506 application which demonstrates most of the features of Deform,
507 including most of the widget and data types available for use within
ac9eaea @davidjb Minor documentation updates: link + RichTextWidget
davidjb authored
508 an application that uses Deform.
Something went wrong with that request. Please try again.