Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Added WTForms documentation.

  • Loading branch information...
commit ce18d4575dd8468878668d777d83448eeae4fd0d 1 parent 73a47a0
@mitsuhiko authored
View
3  docs/conf.py
@@ -242,5 +242,6 @@
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
}
View
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
View
2  docs/patterns/flashing.rst
@@ -1,3 +1,5 @@
+.. _message-flashing-pattern:
+
Message Flashing
================
View
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
View
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>
View
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.
Please sign in to comment.
Something went wrong with that request. Please try again.