Browse Source

Added WTForms documentation.

pull/1638/head
Armin Ronacher 15 years ago
parent
commit
ce18d4575d
  1. 3
      docs/conf.py
  2. 8
      docs/installation.rst
  3. 2
      docs/patterns/flashing.rst
  4. 1
      docs/patterns/index.rst
  5. 109
      docs/patterns/wtforms.rst
  6. 2
      docs/quickstart.rst

3
docs/conf.py

@ -242,5 +242,6 @@ latex_documents = [
intersphinx_mapping = {
'http://docs.python.org/dev': None,
'http://werkzeug.pocoo.org/documentation/dev/': None,
'http://www.sqlalchemy.org/docs/': None
'http://www.sqlalchemy.org/docs/': None,
'http://wtforms.simplecodes.com/docs/0.5/': None
}

8
docs/installation.rst

@ -96,14 +96,6 @@ This is possible as well, but I would not recommend it. Just run
(Run it in an Admin shell on Windows systems and without the `sudo`).
The Drop into Place Version
---------------------------
Now I really don't recommend this way on using Flask, but you can do that
of course as well. Download the `dip` zipfile from the website and unzip
it next to your application.
.. _windows-easy-install:
`easy_install` on Windows

2
docs/patterns/flashing.rst

@ -1,3 +1,5 @@
.. _message-flashing-pattern:
Message Flashing
================

1
docs/patterns/index.rst

@ -16,5 +16,6 @@ end of the request, the database connection is closed again.
packages
sqlite3
sqlalchemy
wtforms
templateinheritance
flashing

109
docs/patterns/wtforms.rst

@ -0,0 +1,109 @@
Form Validation with WTForms
============================
When you have to work with form data submitted by a browser view code
quickly becomes very hard to read. There are libraries out there designed
to make this process easier to manage. One of them is WTForms which we
will handle here. If you find yourself in the situation of having many
forms, you might want to give it a try.
When you are working with WTForms you have to define your forms as classes
first. I recommend breaking up the application into multiple modules
(:ref:`larger-applications`) for that and adding a separate module for the
forms.
The Forms
---------
This is an example form for a typical registration page::
from wtforms import Form, BooleanField, TextField, validators
class RegistrationForm(Form):
username = TextField('Username', [validators.Length(min=4, max=25)])
email = TextField('Email Address', [validators.Length(min=6, max=35)])
password = PasswordField('New Password', [Required(),
EqualTo('confirm', mesage='Passwords must match')])
confirm = PasswordField('Repeat Password')
accept_tos = BooleanField('I accept the TOS', [validators.Required()])
In the View
-----------
In the view function, the usage of this form looks like this::
@app.route('/register', methods=['GET', 'POST'])
def register():
form = RegistrationForm(request.form)
if request.method == 'POST' and form.validate():
user = User(form.username.data, form.email.data,
form.password.data)
db_session.add(user)
flash('Thanks for registering')
redirect(url_for('login'))
return render_template('register.html', form=form)
Notice that we are implying that the view is using SQLAlchemy here
(:ref:`sqlalchemy-pattern`) but this is no requirement of course. Adapt
the code as necessary.
Things to remember:
1. create the form from the request :attr:`~flask.request.form` value if
the data is submitted via the HTTP `POST` method and
:attr:`~flask.request.args` if the data is submitted as `GET`.
2. to validate the data, call the :func:`~wtforms.form.Form.validate`
method which will return `True` if the data validates, `False`
otherwise.
3. to access individual values from the form, access `form.<NAME>.data`.
Forms in Templates
------------------
Now to the template side. When you pass the form to the templates you can
easily render them there. Look at the following example template to see
how easy this is. WTForms does half the form generation for us already.
To make it even nicer, we can write a macro that renders a field with
label and a list of errors if there are any.
Here an example `_formhelpers.html` template with such a macro:
.. sourcecode:: html+jinja
{% macro render_field(field) %}
<dt>{{ field.label }}
<dd>{{ field(**kwargs)|safe }}
{% if field.errors %}
<ul class="errors">
{% for error in field.errors %}
<li>{{ error }}</li>
{% endfor %}
</ul>
{% endif %}
</dd>
{% endmacro %}
This macro accepts a couple of keyword arguments that are forwarded to
WTForm's field function that renders the field for us. They keyword
arguments will be inserted as HTML attributes. So for example you can
call ``render_field(form.username, class='username')`` to add a class to
the input element. Note that WTForms returns standard Python unicode
strings, so we have to tell Jinja2 that this data is already HTML escaped
with the `|safe` filter.
Here the `register.html` template for the function we used above which
takes advantage of the `_formhelpers.html` template:
.. sourcecode:: html+jinja
{% from "_formhelpers.html" import render_field %}
<form method="POST" action="/register">
<dl>
{{ render_field(form.username) }}
{{ render_field(form.email) }}
{{ render_field(form.password) }}
{{ render_field(form.confirm) }}
{{ render_field(form.accept_tos) }}
</dl>
<p><input type=submit value=Register>
</form>

2
docs/quickstart.rst

@ -368,7 +368,7 @@ u'Marked up \xbb HTML'
.. [#] Unsure what that :class:`~flask.g` object is? It's something you
can store information on yourself, check the documentation of that
object (:class:`~flask.g`) and the :ref:`database-pattern` for more
object (:class:`~flask.g`) and the :ref:`sqlite3` for more
information.

Loading…
Cancel
Save