20. Reference of kay.utils.forms module

This forms module is originally derived from Zine project hosted at: http://zine.pocoo.org/

class kay.utils.forms.Widget(field, name, value, all_errors)

Bases: kay.utils.forms._Renderable

Baseclass for all widgets. All widgets share a common interface that can be used from within templates.

Take this form as an example:

>>> class LoginForm(Form):
...     username = TextField(required=True)
...     password = TextField(widget=PasswordInput)
...     flags = MultiChoiceField(choices=[1, 2, 3])
...
>>> form = LoginForm()
>>> form.validate({'username': '', 'password': '',
...                'flags': [1, 3]})
False
>>> widget = form.as_widget()

You can get the subwidgets by using the normal indexing operators:

>>> username = widget['username']
>>> password = widget['password']

To render a widget you can usually invoke the render() method. All keyword parameters are used as HTML attribute in the resulting tag. You can also call the widget itself (username() instead of username.render()) which does the same if there are no errors for the field but adds the default error list after the widget if there are errors.

Widgets have some public attributes:

errors

gives the list of errors:

>>> username.errors
[u'This field is required.']

This error list is printable:

>>> print username.errors()
<ul class="errors"><li>This field is required.</li></ul>

Like any other sequence that yields list items it provides as_ul and as_ol methods:

>>> print username.errors.as_ul()
<ul><li>This field is required.</li></ul>

Keep in mind that widget.errors() is equivalent to widget.errors.as_ul(class_='errors', hide_empty=True).

value

returns the value of the widget as primitive. For basic widgets this is always a string, for widgets with subwidgets or widgets with multiple values a dict or a list:

>>> username.value
u''
>>> widget['flags'].value
[u'1', u'3']

name gives you the name of the field for form submissions:

>>> username.name
'username'

Please keep in mind that the name is not always that obvious. Zine supports nested form fields so it’s a good idea to always use the name attribute.

id

gives you the default domain for the widget. This is either none if there is no idea for the field or f_ + the field name with underscores instead of dots:

>>> username.id
'f_username'

all_errors

like errors but also contains the errors of child widgets.
all_errors
The current errors and the errors of all child widgets.
as_dd(**attrs)
Return a dt/dd item.
errors
The direct errors of this widget.
help_text
The help text of the widget.
hidden()
Return one or multiple hidden fields for the current value. This also handles subwidgets. This is useful for transparent form data passing.
id
The proposed id for this widget.
label
The label for the widget.
localname
The local name of the field.
value
The primitive value for this widget.
value_for_freeze
The value for frozen form widgets.
class kay.utils.forms.Input(field, name, value, all_errors)

Bases: kay.utils.forms.Widget

A widget that is a HTML input field.

class kay.utils.forms.FileInput(field, name, value, all_errors)

Bases: kay.utils.forms.Input

A widget for uploading files.

class kay.utils.forms.TextInput(field, name, value, all_errors)

Bases: kay.utils.forms.Input

A widget that holds text.

class kay.utils.forms.PasswordInput(field, name, value, all_errors)

Bases: kay.utils.forms.TextInput

A widget that holds a password.

class kay.utils.forms.HiddenInput(field, name, value, all_errors)

Bases: kay.utils.forms.Input

A hidden input field for text.

class kay.utils.forms.Textarea(field, name, value, all_errors)

Bases: kay.utils.forms.Widget

Displays a textarea.

class kay.utils.forms.Checkbox(field, name, value, all_errors)

Bases: kay.utils.forms.Widget

A simple checkbox.

as_dd(**attrs)
Return a dt/dd item.
as_li(**attrs)
Return a li item.
with_help_text(**attrs)
Render the checkbox with help text.
class kay.utils.forms.SelectBox(field, name, value, all_errors)

Bases: kay.utils.forms.Widget

A select box.

class kay.utils.forms.RadioButton(parent, value, label)

Bases: kay.utils.forms._InputGroupMember

A radio button in an input group.

class kay.utils.forms.GroupCheckbox(parent, value, label)

Bases: kay.utils.forms._InputGroupMember

A checkbox in an input group.

class kay.utils.forms.RadioButtonGroup(field, name, value, all_errors)

Bases: kay.utils.forms._InputGroup

A group of radio buttons.

subwidget
alias of RadioButton
class kay.utils.forms.CheckboxGroup(field, name, value, all_errors)

Bases: kay.utils.forms._InputGroup

A group of checkboxes.

subwidget
alias of GroupCheckbox
class kay.utils.forms.Field(label=None, help_text=None, validators=None, widget=None, messages=None, default=no default)

Bases: object

Abstract field base class.

apply_validators(value)
Applies all validators on the value.
bound
True if the form is bound.
convert(value)
This can be overridden by subclasses and performs the value conversion.
should_validate(value)

Per default validate if the value is not None. This method is called before the custom validators are applied to not perform validation if the field is empty and not required.

For example a validator like is_valid_ip is never called if the value is an empty string and the field hasn’t raised a validation error when checking if the field is required.

to_primitive(value)

Convert a value into a primitve (string or a list/dict of lists, dicts or strings).

This method must never fail!

widget
alias of TextInput
class kay.utils.forms.Multiple(field, label=None, help_text=None, min_size=None, max_size=None, validators=None, widget=None, messages=None, default=no default, required=False)

Bases: kay.utils.forms.Field

Apply a single field to a sequence of values.

>>> field = Multiple(IntegerField())
>>> field([u'1', u'2', u'3'])
[1, 2, 3]

Recommended widgets:

  • ListWidget – the default one and useful if multiple complex fields are in use.
  • CheckboxGroup – useful in combination with choices
  • SelectBoxWidget – useful in combination with choices
widget
alias of ListWidget
class kay.utils.forms.CommaSeparated(field, label=None, help_text=None, min_size=None, max_size=None, sep=u', ', validators=None, widget=None, messages=None, default=no default, required=False)

Bases: kay.utils.forms.Multiple

Works like the multiple field but for comma separated values:

>>> field = CommaSeparated(IntegerField())
>>> field(u'1, 2, 3')
[1, 2, 3]

The default widget is a MultipleTextInput but MultipleTextarea would be a possible choices as well.

class kay.utils.forms.LineSeparated(field, label=None, help_text=None, min_size=None, max_size=None, sep=u', ', validators=None, widget=None, messages=None, default=no default, required=False)

Bases: kay.utils.forms.CommaSeparated

Works like CommaSeparated but uses multiple lines:

>>> field = LineSeparated(IntegerField())
>>> field(u'1\n2\n3')
[1, 2, 3]

The default widget is a MultipleTextarea and taht is pretty much the only thing that makes sense for this widget.

class kay.utils.forms.TextField(label=None, help_text=None, required=False, min_length=None, max_length=None, validators=None, widget=None, messages=None, default=no default)

Bases: kay.utils.forms.Field

Field for strings.

>>> field = TextField(required=True, min_length=6)
>>> field('foo bar')
u'foo bar'
>>> field('')
Traceback (most recent call last):
  ...
ValidationError: This field is required.
should_validate(value)
Validate if the string is not empty.
class kay.utils.forms.RegexField(regex, *args, **kwargs)
Bases: kay.utils.forms.TextField
class kay.utils.forms.EmailField(*args, **kwargs)
Bases: kay.utils.forms.RegexField
class kay.utils.forms.DateTimeField(label=None, help_text=None, required=False, rebase=True, validators=None, widget=None, messages=None, default=no default)

Bases: kay.utils.forms.Field

Field for datetime objects.

>>> field = DateTimeField()
>>> field('1970-01-12 00:00')
datetime.datetime(1970, 1, 12, 0, 0)
>>> field('foo')
Traceback (most recent call last):
  ...
ValidationError: Please enter a valid date.
class kay.utils.forms.ModelField(model=None, key=None, label=None, help_text=None, required=False, message=None, validators=None, widget=None, messages=None, default=no default, on_not_found=None, query=None, option_name=None)

Bases: kay.utils.forms.Field

A field that queries for a model.

The first argument is the name of the model. If the key is not given (None) the primary key is assumed. You can specify query parameter on init or anytime you want via set_query() method. It gives you query based option rendering and validation.

Here is an example for setting query after init:

>>> class FormWithModelField(Form):
...    model_field = forms.ModelField(model=TestModel, reuired=True)
>>> form = FormWithModelField()
... query = TestModel.all().filter('user =', user.key())
... form.model_field.set_query(query)

If the Model class has __unicode__() method, the return value of this method will be used for rendering the text in an option tag. If there’s no __unicode__() method, Model.__repr__() will be used for this purpose. You can override this behavior by passing an attribute name used for the option tag’s value with option_name keyword argument on initialization of this field.

choices
You can set choices directly via this attribute.
set_query(query)
You can set query directly with this method.
widget
alias of SelectBox
class kay.utils.forms.HiddenModelField(model, key=None, required=False, message=None, validators=None, widget=None, messages=None, default=no default)

Bases: kay.utils.forms.ModelField

A hidden field that points to a model identified by primary key. Can be used to pass models through a form.

widget
alias of HiddenInput
class kay.utils.forms.ChoiceField(label=None, help_text=None, required=False, choices=None, validators=None, widget=None, messages=None, default=no default)

Bases: kay.utils.forms.Field

A field that lets a user select one out of many choices.

A choice field accepts some choices that are valid values for it. Values are compared after converting to unicode which means that 1 == "1":

>>> field = ChoiceField(choices=[1, 2, 3])
>>> field('1')
1
>>> field('42')
Traceback (most recent call last):
  ...
ValidationError: Please enter a valid choice.

Two values a and b are considered equal if either a == b or primitive(a) == primitive(b) where primitive is the primitive of the value. Primitives are created with the following algorithm:

  1. if the object is None the primitive is the empty string
  2. otherwise the primitive is the string value of the object

A choice field also accepts lists of tuples as argument where the first item is used for comparing and the second for displaying (which is used by the SelectBoxWidget):

>>> field = ChoiceField(choices=[(0, 'inactive'), (1, 'active')])
>>> field('0')
0

Because all fields are bound to the form before validation it’s possible to assign the choices later:

>>> class MyForm(Form):
...     status = ChoiceField()
...
>>> form = MyForm()
>>> form.status.choices = [(0, 'inactive', 1, 'active')]
>>> form.validate({'status': '0'})
True
>>> form.data
{'status': 0}

If a choice field is set to “not required” and a SelectBox is used as widget you have to provide an empty choice or the field cannot be left blank.

>>> field = ChoiceField(required=False, choices=[('', _('Nothing')),
...                                              ('1', _('Something'))])
widget
alias of SelectBox
class kay.utils.forms.MultiChoiceField(label=None, help_text=None, choices=None, min_size=None, max_size=None, validators=None, widget=None, messages=None, default=no default)

Bases: kay.utils.forms.ChoiceField

A field that lets a user select multiple choices.

class kay.utils.forms.NumberField(label=None, help_text=None, required=False, min_value=None, max_value=None, validators=None, widget=None, messages=None, default=no default)

Bases: kay.utils.forms.Field

Field for numbers.

>>> field = IntegerField(min_value=0, max_value=99)
>>> field('13')
13
>>> field('thirteen')
Traceback (most recent call last):
  ...
ValidationError: Please enter a whole number.
>>> field('193')
Traceback (most recent call last):
  ...
ValidationError: Ensure this value is less than or equal to 99.
class kay.utils.forms.IntegerField(label=None, help_text=None, required=False, min_value=None, max_value=None, validators=None, widget=None, messages=None, default=no default)

Bases: kay.utils.forms.NumberField

Field for integers.

>>> field = IntegerField(min_value=0, max_value=99)
>>> field('13')
13
>>> field('thirteen')
Traceback (most recent call last):
  ...
ValidationError: Please enter a whole number.
>>> field('193')
Traceback (most recent call last):
  ...
ValidationError: Ensure this value is less than or equal to 99.
class kay.utils.forms.FloatField(label=None, help_text=None, required=False, min_value=None, max_value=None, validators=None, widget=None, messages=None, default=no default)

Bases: kay.utils.forms.NumberField

Field for floats.

>>> field = IntegerField(min_value=0, max_value=99)
>>> field('13.4')
13.4
>>> field('thirteen')
Traceback (most recent call last):
  ...
ValidationError: Please enter a float number.
>>> field('193.2')
Traceback (most recent call last):
  ...
ValidationError: Ensure this value is less than or equal to 99.
class kay.utils.forms.FileField(label=None, help_text=None, required=False, validators=None, widget=None, messages=None, default=no default)

Bases: kay.utils.forms.Field

Field for file upload.

widget
alias of FileInput
class kay.utils.forms.BooleanField(label=None, help_text=None, required=False, validators=None, widget=None, messages=None, default=no default)

Bases: kay.utils.forms.Field

Field for boolean values.

>>> field = BooleanField()
>>> field('1')
True
>>> field = BooleanField()
>>> field('')
False
widget
alias of Checkbox
class kay.utils.forms.Form(initial=None, action='', use_confirmation=False)

Bases: object

Form base class.

>>> class PersonForm(Form):
...     name = TextField(required=True)
...     age = IntegerField()
>>> form = PersonForm()
>>> form.validate({'name': 'johnny', 'age': '42'})
True
>>> form.data['name']
u'johnny'
>>> form.data['age']
42

Let’s cause a simple validation error:

>>> form = PersonForm()
>>> form.validate({'name': '', 'age': 'fourty-two'})
False
>>> print form.errors['age'][0]
Please enter a whole number.
>>> print form.errors['name'][0]
This field is required.

You can also add custom validation routines for fields by adding methods that start with the prefix validate_ and the field name that take the value as argument. For example:

>>> class PersonForm(Form):
...     name = TextField(required=True)
...     age = IntegerField()
...
...     def validate_name(self, value):
...         if not value.isalpha():
...             raise ValidationError(u'The value must only contain letters')
>>> form = PersonForm()
>>> form.validate({'name': 'mr.t', 'age': '42'})
False
>>> form.errors
{'name': [u'The value must only contain letters']}

You can also validate multiple fields in the context of other fields. That validation is performed after all other validations. Just add a method called context_validate that is passed the dict of all fields:

>>> class RegisterForm(Form):
...     username = TextField(required=True)
...     password = TextField(required=True)
...     password_again = TextField(required=True)
...
...     def context_validate(self, data):
...         if data['password'] != data['password_again']:
...             raise ValidationError(u'The two passwords must be the same')
>>> form = RegisterForm()
>>> form.validate({'username': 'admin', 'password': 'blah',
...                'password_again': 'blag'})
...
False
>>> form.errors
{None: [u'The two passwords must be the same']}

Forms can be used as fields for other forms. To create a form field of a form you can call the as_field class method:

>>> field = RegisterForm.as_field()

This field can be used like any other field class. What’s important about forms as fields is that validators don’t get an instance of RegisterForm passed as form / self but the form where it’s used in if the field is used from a form.

Form fields are bound to the form on form instanciation. This makes it possible to modify a particular instance of the form. For example you can create an instance of it and drop some fiels by using del form.fields['name'] or reassign choices of choice fields. It’s however not easily possible to add new fields to an instance because newly added fields wouldn’t be bound. The fields that are stored directly on the form can also be accessed with their name like a regular attribute.

Example usage:

>>> class StatusForm(Form):
...     status = ChoiceField()
...
>>> StatusForm.status.bound
False
>>> form = StatusForm()
>>> form.status.bound
True
>>> form.status.choices = [u'happy', u'unhappy']
>>> form.validate({'status': u'happy'})
True
>>> form['status']
u'happy'

Fields support default values. These however are not as useful as you might think. These defaults are just annotations for external handling. The form validation system does not respect those values.

They are for example used in the configuration system.

Example:

>>> field = TextField(default=u'foo')
as_widget()
Return the form as widget.
csrf_token
The unique CSRF security token for this form.
has_changed
True if the form has changed.
is_valid
True if the form is valid.
reset()
Resets the form.
validate(data, files=None)
Validate the form against the data passed.

Previous topic

19. Running Tests

Next topic

21. Using db_hook feature

This Page