Re: multiple or combined messages from compound validator

Mike Orr <[email protected]> Wed, 21 Jul 2010 10:18:45 -0700
Newsgroups gmane.comp.python.formencode
Message-ID <[email protected]>
On Tue, Jul 20, 2010 at 10:32 PM, Ed Hillis <[email protected]> wrote:
> I would like to have a compound validator give the error message for each of
> it elements. For example, if my field could not be empty and it required an
> Int, the output would be something like:
>
> field: 'Please enter something, Must be an integer'
>
> instead of just showing one or the other. Is there a built-in way to do
> this? I am completely new here, and may be overlooking any obvious solution.
> Thanks -Ed

I'm not quite sure what you mean. I use the following for select lists
whose value is an int:

===
class SelectInt(v.FancyValidator):
    """A combination of the Int and OneOf validators with a custom message"""
    __unpackargs__ = ("list",)
    not_empty = True

    def _to_python(self, value, state):
        try:
            return int(value)
        except ValueError:
            self._invalid(value, state)

    _from_python = _to_python

    def validate_python(self, value, state):
        if value not in self.list:
            self._invalid(value, state)

    def _invalid(self, value, state):
        message = "please choose an item from the list"
        raise v.Invalid(message, value, state)
===

I also use a custom error message for regular int validators:

===
class Int(v.Int):
    messages = {
        "integer": _("Please enter a numeric value"),
        }
===

If by "compound validator" you mean that it validates several widgets
together, you can do that with a chained validator, which takes a dict
of values and error messages rather than scalar strings.

For nested validators (e.g., a latitude-longitude widget with multiple
fields for degrees, minutes, and seconds), you'd create a Schema
validator for it, and make sure that 'pre_validators =
[NestedVariables()]'. Then the Python value of the subwidget would
appear as a nested dict in Python, and your form would contain widgets
like this:

.<input name="lat_lon.lat_deg" type="text" />

-- 
Mike Orr <[email protected]>

------------------------------------------------------------------------------
This SF.net email is sponsored by Sprint
What will you do first with EVO, the first 4G phone?
Visit sprint.com/first -- http://p.sf.net/sfu/sprint-com-first