Monday 30 April 2012

WTForms - validating values against other others

Validating form values against each other

Again very basic - I wish to make sure that the value of a field entered is greater than another field. To do this I needed to create a custom validator. This custom validator was based on the EqualTo validator. I called it's class GreaterThan.

I could edit the wtforms/validators.py file and add a new validator in there how ever this would not make library upgrades easy. Instead I created a mywtforms directory within which I created a __init__.py file which when

 import mywtforms 

is used will load the code in this file. The contents of the __init__.py file look like:


#need help figuring out what to import here I've creating so methods that inherit from wtforms and its structure
#TODO re-read : http://docs.python.org/tutorial/modules.html
from wtforms import validators, widgets
from wtforms.widgets import *
from wtforms.fields import *
from wtforms.form import Form
from wtforms.validators import ValidationError


class GreaterThan(object):
    """
    Compares the value of two fields the value of self is to be greater than the supplied field.

    :param fieldname:
        The name of the other field to compare to.
    :param message:
        Error message to raise in case of a validation error. Can be
        interpolated with `%(other_label)s` and `%(other_name)s` to provide a
        more helpful error.
    """
    def __init__(self, fieldname, message=None):
        self.fieldname = fieldname
        self.message = message

    def __call__(self, form, field):
        try:
            other = form[self.fieldname]
        except KeyError:
            raise ValidationError(field.gettext(u"Invalid field name '%s'.") % self.fieldname)
        if field.data != '' and field.data < other.data:
            d = {
                'other_label': hasattr(other, 'label') and other.label.text or self.fieldname,
                'other_name': self.fieldname
            }
            if self.message is None:
                self.message = field.gettext(u'Field must be greater than %(other_name)s.')

            raise ValidationError(self.message % d)

Later I plan to split up __init__.py and place the code into directories mirroring those in the wtforms directory

To use the validator I could create a form such as:


import re

def filter_field(value):
   return re.sub('\d{2}$','00',value)

class MyForm(Form):
   field_one = TextField('Field 1',validators=[validators.Regexp('^[0-9]*)',
                             message='Must be an integer')],
                             filters=[lambda x: x*100, filter_field])
   field_two = TextField('Field 1',validators=[validators.Regexp('^[0-9]*)',
                             message='Must be an integer'),GreaterThann('field_one','field two must be greater than field one')],
                             filters=[lambda x: x*100, filter_field])

No comments:

Post a Comment