Hello

I looked the source and saw I can specify a form and a validators
in a @validate() like that

@validate(form=my_form, validators=Wrapper(my_controller_method))

I use the validator to make extended validation on the form fields,
and take advantage of the form redisplay provided by @error_handling

My Wrapper use same trick as controller method use to pass the fields
as arguments, for example my_controller_method looks like

    def validate_password(user_name, password, password2):
        user=model.User.get_by(user_name=user_name)
        if password==user.password:
            raise InvalidField('Password must be different of previous
one', 'password')
        return dict(user=user)

Here InvalidField is raised and converted into validator.Invalid by
the wrapper to let @error_handler do its job and redisplay the form.

To not loose my freshly retrieved "user" object, I return
it to my wrapper that will update the field_dict.
The "normal" controller method will use this user object to finish the
job.

    @turbogears.expose(template=".templates.save_password")
    @validate(form=password_form,
validators=Wrapper(validate_password))
    @error_handler(reset_password)
    def save_password(self, user_name, password, user, **kwargs):
        user.password=password
        session.flush()
        return dict(user_name=user_name, msg='Password succesfully
reset')

Here is my wrapper code and InvaliedField class:

class InvalidField:
    def __init__(self, msg, field_name):
        self.msg=msg
        self.field_name=field_name

class ValidatorFunctionConverter(validators.FormValidator):

    validate_partial_form = False
    __unpackargs__ = ('validator_func',)

    def validate_python(self, field_dict, state):
        # filter parameters to match the function's arguments
        to_args, to_kw=tg_util.to_kw(self.validator_func, [],
dict(field_dict), start=0)
        args, kw=tg_util.adapt_call(self.validator_func, [],
dict(to_kw), start=0)

        try:
            result=self.validator_func(**kw)
        except InvalidField, e:
            # convert the InvalidField exception into Invalid one
            raise validators.Invalid(e.msg, field_dict, state,
error_dict={e.field_name: e.msg})

        if result is None:
            pass
        elif isinstance(result, types.DictType):
            field_dict.update(result)
        else:
            # FiXME: generate a better exception
            raise 'validator_func "%s" return a %s should return None
or dictionary' % (self.validator_func.__name__, type(result).__name__)

To make this work I had to change how @validate work in
controller.py :-)
I just changed one line :

<             if validators:
---
>             if not errors and validators:

Here is more context for a better understanding

              if form:
                  value = kw.copy()
                  try:
                      kw.update(form.validate(value, state))
                  except Invalid, e:
                      errors = e.unpack_errors()
                      cherrypy.request.validation_exception = e
                  cherrypy.request.validated_form = form

!             if not errors and validators:
                  if isinstance(validators, dict):
                       .....
                  else:
                    try:
                        value = kw.copy()
                        kw.update(validators.to_python(value, state))
                    except Invalid, e:
                        errors = e.unpack_errors()
                        cherrypy.request.validation_exception = e


The trick is that "form" will initialize
cherrypy.request.validated_form = form
That way, when my "extended" validator raise and InvalidField
the @error_handler will redisplay the form too :-)

I changed
             if not errors and validators:
because I dont want my validator to be called if the form is not
valid,
because some field could be missing or simply invalid to call
validate_password(user_name, password, password2)

Any comments are welcome

I did it :-)


--
Alain Spineux
aspineux gmail com
May the sources be with you


--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"TurboGears" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/turbogears?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to