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
-~----------~----~----~----~------~----~------~--~---