tipfy.ext.wtforms ¶
This extension provides enhanced WTForms support in tipfy. WTForms is a library for form validation and rendering. It is easy to use, extensible, explicit and magic-free, like tipfy. :)
tipfy.ext.wtforms extends WTForms to provide:
- Built-in support for
<input type="file">(not handled by WTForms for being framework dependent). - Built-in ReCaptcha support.
- Built-in CSRF protection support.
In the future it will also provide i18n capability.
Creating forms¶
Let's see how it works in a basic contact form example. For a complete reference, check WTForms documentation.
You define a form in a class that extends wtforms.Form. We wrap it in the
tipfy.ext.wtforms so that it also accepts a request object in the constructor.
Each form field is an attribute of the class:
handlers.py
from tipfy.ext.wtforms import Form, fields
class ContactForm(Form):
name = fields.TextField('Name')
email = fields.TextField('Email')
message = fields.TextAreaField('Message')
That's it. Our first form is defined. Let's use it in a handler:
handlers.py
from tipfy import RequestHandler, cached_property, redirect
from tipfy.ext.jinja2 import Jinja2Mixin
class MyHandler(RequestHandler, Jinja2Mixin):
def get(self, **kwargs):
"""To display a form, we simply pass the form instance to the template.
"""
context = {
'form': self.form,
}
# Returns a rendered template, passing the 'form' instance as variable.
return self.render_response('test_form.html', **context)
def post(self, **kwargs):
"""To process a form, we validate it and pass the form instance to the
template.
"""
# Validate the form.
if self.form.validate():
# Form is valid. Use the form data and redirect the user to the
# final destination.
name = self.form.name.data
email = self.form.email.data
message = self.form.message.data
# ... do something with the collected data ...
return redirect('/')
# Since the form didn't validate, render it again using self.get().
return self.get(**kwargs)
@cached_property
def form(self):
"""We define a form as a cached property instantiated on first call.
It is constructed passing the request object to populate it.
"""
return ContactForm(self.request)
Now we have a handler that displays and processes our form. The form template is still missing, though, so let's create one:
test_form.html
{% from '_form_macros.html' import form_field %}
<html>
<title>Contact Form</title>
<body>
<h1>Contact form</h1>
<form method="post" action="" enctype="multipart/form-data" class="tipfy-form">
<ol>
<li>{{ form_field(form.name, class='medium') }}</li>
<li>{{ form_field(form.email, class='medium') }}</li>
<li>{{ form_field(form.message, class='large') }}</li>
</ol>
<fieldset class="submit">
<input type="submit" name="submit" value="Send" class="submit">
</fieldset>
</form>
</body>
</html>
In this template, we use these Jinja2 Macros for forms to build the form markup.
Also, for this example, try using these form stylesheets. They're some basic styles for a good looking form.
CSRF protection¶
The Form object also has the ability to protect against CSRF. To enable it, set csrf_protection to True when
defining the form, or pass csrf_protection=True when instantiating it.
from tipfy.ext.wtforms import Form, fields
class ContactForm(Form):
csrf_protection = True
name = fields.TextField('Name')
email = fields.TextField('Email')
message = fields.TextAreaField('Message')
A hidden field csrf_token will be added to the form and automatically populated.
You must render this field when displaying the form.
Also, to use CSRF you must have sessions enabled, and you must
instantiate the form passing the request object. This is because the token is validated
using the current session, which requires a Request object.
Extension Reference¶
- Name: tipfy.ext.wtforms
- Author: Rodrigo Moraes
- License: BSD
- Tags: form, forms, validation, sanitization
- URL: http://www.tipfy.org/wiki/extensions/wtforms/
- PyPi page: http://pypi.python.org/pypi/tipfy.ext.wtforms/
- Source code: http://code.google.com/p/tipfy-ext-wtforms/
- Issue tracker: http://code.google.com/p/tipfy-ext-wtforms/issues/list
- Version: latest
- Edited by moraes on 7/20/10 11:16 AM
- Save on Delicious | Submit to Reddit
- History
- Edit
