web2py allows us to write custom form validators, by pattern validators in web2py are UPPERCASE
Hi Pythonista! I know that you are now wondering why does not follow PEP8 name convention? Ok, this is the web2py way, it breaks PEP8 a bit, but it has a good reason The naming convention is for preventing conflicts between objects named
There are two types of validators
VALIDATOR: It validates if some data is valid or if follow some pattern
TRANSFORMATION; It only takes the entered value and returns the transformed value
class VALIDATOR(object): def __init__(self, error_message="SOMETHING WRONG"): self.error_message = error_message def __call__(self, value): error = None # CONDITION COMES HERE if "ERROR": error = self.error_message # IF error != None - value is invalid return (value, error) class TRANSFORMATION(object): def __init__(self, search, replace): self.search = search self.replace = replace def __call__(self, value): error = None try: # TRANSFORMATION COMES HERE value = value.replace(self.search, self.replace) except: error = "Not possible to transform" return (value, error)
How to write my own validator
Follow the patterns above, lets see some example
Validate if a zip-code starts with "051"
By some reason our system does not allows registering from other regions out of "051" zip code
class IS_ALLOWED_ZIP_CODE(object): def __init__(self, zip_area, error_message="Zip code not allowed"): self.zip_area = zip_ares self.error_message = error_message def __call__(self, value): error = None value = value.strip() if not value.startswith(self.zip_area): error = self.error_message return (value, error)
Now you can use this in your models
db.define_table("address", ... Field("zipcode", requires=IS_ALLOWED_ZIP_CODE("051"), notnull=True) ....)
Simply like that! now your forms will fire the "Not allowed Zip Code" when users tries to input a zip code as "04509-890"
Transform some text
class REPLACE_TEXT(object): def __init__(self, search, replace): self.search = str(search) self.replace = str(replace) def __call__(self, value): error = None try: value = value.replace(self.search, self.replace) except: error = "Error replacing" return (value, error)
In the same way you now replace values in your forms
Example: User enters latitude, longitude with "," and you replace with "."
replace_comma_with_dot = REPLACE_TEXT(",", ".") db.define_table("address", Field("latitude", requires=replace_comma_with_dot), Field("longitude", requires=replace_comma_with_dot) )
HOW IT WORKS?
web2py forms and DAL
validate_and_* methods has a step where it takes all values in
for every field in the table, so it takes the entered value and do a call to the validator class
as you can see, the validator implements the
__call__ magic method, which means that it will execute when
the instance of the class are called. Yes, instances are callables
class Foo(object): def __call__(self, *args): print("I've been called with some args %s" % str(args)) >>> foo = Foo() >>> foo("web2py", "rocks") # we are calling the instance directly I've been called with some args ('web2py', 'rocks')
also, is it possible to do some validation and transformation using compute for fields and form events as onvalidation and onaccepts
comments powered by Disqus Go Top