Matthew Wilson
2008-11-25 21:50:49 UTC
NOTE: I am sending this again, because I'm not sure my first attempt
made it. The first attempt had an attachment. In this case, the
patch is inline.
I wrote a blog post today with a description on how to verify one date
field is before another. This patch contains the text of that blog
post along with a new "Examples" section to the bottom of
Validator.txt.
There is some weirdness going on with the headings in the new examples
section. I tried to use toctree but couldn't figure it out, so
hopefully somebody else can tweak this so it is more useful.
Matt
PATCH
Index: docs/schema_validator_example.rst
===================================================================
--- docs/schema_validator_example.rst (revision 0)
+++ docs/schema_validator_example.rst (revision 0)
@@ -0,0 +1,110 @@
+++++++++++++++++++++++++++++++++++++++++++++++++++
+Use FormEncode to verify one date precedes another
+++++++++++++++++++++++++++++++++++++++++++++++++++
+
+I have a form on my site that lets people choose a start date and a stop
+date. Then I show statistics for that date range. I wrote a FormEncode
+schema to verify that the start date is before the stop date.
+
+Here's the code
+===============
+
+::
+
+ # This is in a file named formencodefun.py
+ from formencode import Schema
+ from formencode.validators import DateConverter, FancyValidator, Invalid
+
+ class DateCompare(FancyValidator):
+ messages = dict(invalid="Start date must be before stop date")
+
+ def validate_python(self, field_dict, state):
+
+ start_date = field_dict['start_date']
+ stop_date = field_dict['stop_date']
+
+ if start_date > stop_date:
+ msg = self.message('invalid', state)
+
+ raise Invalid(msg, field_dict, state,
+ error_dict=dict(stop_date=msg))
+
+ class MySchema(Schema):
+ start_date = DateConverter()
+ stop_date = DateConverter()
+
+ chained_validators = [DateCompare()]
+
+Usage
+=====
+
+::
+
+ >>> from formencodefun import MySchema
+ >>> s = MySchema()
+ >>> d1 = {'start_date':'11-02-2008', 'stop_date':'11-15-2008'}
+ >>> d2 = {'start_date':'11-15-2008', 'stop_date':'11-02-2008'}
+ >>> s.to_python(d1)
+ {'stop_date': datetime.date(2008, 11, 15), 'start_date':
+ datetime.date(2008, 11, 2)}
+ >>> s.to_python(d2)
+ ------------------------------------------------------------
+ Traceback (most recent call last):
+ File "<ipython console>", line 1, in <module>
+ File
+ "/home/matt/virtualenvs/scratch/lib/python2.5/site-packages/FormEncode-1.1-py2.5.egg/formencode/api.py",
+ line 400, in to_python
+ value = tp(value, state)
+ File
+ "/home/matt/virtualenvs/scratch/lib/python2.5/site-packages/FormEncode-1.1-py2.5.egg/formencode/schema.py",
+ line 200, in _to_python
+ new = validator.to_python(new, state)
+ File
+ "/home/matt/virtualenvs/scratch/lib/python2.5/site-packages/FormEncode-1.1-py2.5.egg/formencode/api.py",
+ line 403, in to_python
+ vp(value, state)
+ File "formencodefun.py", line 18, in validate_python
+ error_dict=dict(stop_date=msg))
+ Invalid: Start date must be before stop date
+
+How it works
+============
+
+Notice when I run s.to_python(d1), I get a dictionary back with the the
+values for start_date and stop_date replaced with datetime.date objects.
+
+Then when I run my schema on d2, where the start_date is after the
+stop_date, my schema raises an Invalid exception. In a web framework
+like TurboGears, there is some exception handler that will catch that
+exception and take that error dictionary and redraw the form and print
+my error message.
+
+Notice that the DateConverters first take my strings and turn them into
+datetime.date objects before the test in DateCompare. FormEncode runs
+the chained validators after it runs the individual validators.
+
+In this case, I just want to make sure that the start date precedes the
+stop date. I have written other validators that add extra keys into the
+field dict or change the values, but I want to keep this example simple.
+
+If the first DateConverters fail, then the chained validators never
+run::
+
+ >>> s.to_python({'start_date':'UNPARSEABLE', 'stop_date':'11-20-2008'})
+ ------------------------------------------------------------
+ Traceback (most recent call last):
+ File "<ipython console>", line 1, in <module>
+ File
+ "/home/matt/virtualenvs/scratch/lib/python2.5/site-packages/FormEncode-1.1-py2.5.egg/formencode/api.py",
+ line 400, in to_python
+ value = tp(value, state)
+ File
+ "/home/matt/virtualenvs/scratch/lib/python2.5/site-packages/FormEncode-1.1-py2.5.egg/formencode/schema.py",
+ line 197, in _to_python
+ error_dict=errors)
+ Invalid: start_date: Please enter the date in the form mm/dd/yyyy
+
+When my DateCompare validator is run, I can be confident that the
+objects with the keys start_date and stop_date in the field_dict have
+already been converted to datetime.date objects.
+
Index: docs/Validator.txt
===================================================================
--- docs/Validator.txt (revision 3696)
+++ docs/Validator.txt (working copy)
@@ -637,3 +637,9 @@
is hard to access the ``'action'`` key in the example; storing the
options (action.option and action.confirm) under another key would be
preferable.
+
+
+Examples
+========
+
+.. include:: schema_validator_example.rst
END
made it. The first attempt had an attachment. In this case, the
patch is inline.
I wrote a blog post today with a description on how to verify one date
field is before another. This patch contains the text of that blog
post along with a new "Examples" section to the bottom of
Validator.txt.
There is some weirdness going on with the headings in the new examples
section. I tried to use toctree but couldn't figure it out, so
hopefully somebody else can tweak this so it is more useful.
Matt
PATCH
Index: docs/schema_validator_example.rst
===================================================================
--- docs/schema_validator_example.rst (revision 0)
+++ docs/schema_validator_example.rst (revision 0)
@@ -0,0 +1,110 @@
+++++++++++++++++++++++++++++++++++++++++++++++++++
+Use FormEncode to verify one date precedes another
+++++++++++++++++++++++++++++++++++++++++++++++++++
+
+I have a form on my site that lets people choose a start date and a stop
+date. Then I show statistics for that date range. I wrote a FormEncode
+schema to verify that the start date is before the stop date.
+
+Here's the code
+===============
+
+::
+
+ # This is in a file named formencodefun.py
+ from formencode import Schema
+ from formencode.validators import DateConverter, FancyValidator, Invalid
+
+ class DateCompare(FancyValidator):
+ messages = dict(invalid="Start date must be before stop date")
+
+ def validate_python(self, field_dict, state):
+
+ start_date = field_dict['start_date']
+ stop_date = field_dict['stop_date']
+
+ if start_date > stop_date:
+ msg = self.message('invalid', state)
+
+ raise Invalid(msg, field_dict, state,
+ error_dict=dict(stop_date=msg))
+
+ class MySchema(Schema):
+ start_date = DateConverter()
+ stop_date = DateConverter()
+
+ chained_validators = [DateCompare()]
+
+Usage
+=====
+
+::
+
+ >>> from formencodefun import MySchema
+ >>> s = MySchema()
+ >>> d1 = {'start_date':'11-02-2008', 'stop_date':'11-15-2008'}
+ >>> d2 = {'start_date':'11-15-2008', 'stop_date':'11-02-2008'}
+ >>> s.to_python(d1)
+ {'stop_date': datetime.date(2008, 11, 15), 'start_date':
+ datetime.date(2008, 11, 2)}
+ >>> s.to_python(d2)
+ ------------------------------------------------------------
+ Traceback (most recent call last):
+ File "<ipython console>", line 1, in <module>
+ File
+ "/home/matt/virtualenvs/scratch/lib/python2.5/site-packages/FormEncode-1.1-py2.5.egg/formencode/api.py",
+ line 400, in to_python
+ value = tp(value, state)
+ File
+ "/home/matt/virtualenvs/scratch/lib/python2.5/site-packages/FormEncode-1.1-py2.5.egg/formencode/schema.py",
+ line 200, in _to_python
+ new = validator.to_python(new, state)
+ File
+ "/home/matt/virtualenvs/scratch/lib/python2.5/site-packages/FormEncode-1.1-py2.5.egg/formencode/api.py",
+ line 403, in to_python
+ vp(value, state)
+ File "formencodefun.py", line 18, in validate_python
+ error_dict=dict(stop_date=msg))
+ Invalid: Start date must be before stop date
+
+How it works
+============
+
+Notice when I run s.to_python(d1), I get a dictionary back with the the
+values for start_date and stop_date replaced with datetime.date objects.
+
+Then when I run my schema on d2, where the start_date is after the
+stop_date, my schema raises an Invalid exception. In a web framework
+like TurboGears, there is some exception handler that will catch that
+exception and take that error dictionary and redraw the form and print
+my error message.
+
+Notice that the DateConverters first take my strings and turn them into
+datetime.date objects before the test in DateCompare. FormEncode runs
+the chained validators after it runs the individual validators.
+
+In this case, I just want to make sure that the start date precedes the
+stop date. I have written other validators that add extra keys into the
+field dict or change the values, but I want to keep this example simple.
+
+If the first DateConverters fail, then the chained validators never
+run::
+
+ >>> s.to_python({'start_date':'UNPARSEABLE', 'stop_date':'11-20-2008'})
+ ------------------------------------------------------------
+ Traceback (most recent call last):
+ File "<ipython console>", line 1, in <module>
+ File
+ "/home/matt/virtualenvs/scratch/lib/python2.5/site-packages/FormEncode-1.1-py2.5.egg/formencode/api.py",
+ line 400, in to_python
+ value = tp(value, state)
+ File
+ "/home/matt/virtualenvs/scratch/lib/python2.5/site-packages/FormEncode-1.1-py2.5.egg/formencode/schema.py",
+ line 197, in _to_python
+ error_dict=errors)
+ Invalid: start_date: Please enter the date in the form mm/dd/yyyy
+
+When my DateCompare validator is run, I can be confident that the
+objects with the keys start_date and stop_date in the field_dict have
+already been converted to datetime.date objects.
+
Index: docs/Validator.txt
===================================================================
--- docs/Validator.txt (revision 3696)
+++ docs/Validator.txt (working copy)
@@ -637,3 +637,9 @@
is hard to access the ``'action'`` key in the example; storing the
options (action.option and action.confirm) under another key would be
preferable.
+
+
+Examples
+========
+
+.. include:: schema_validator_example.rst
END
--
Matthew Wilson
***@tplus1.com
http://tplus1.com
Matthew Wilson
***@tplus1.com
http://tplus1.com