David Pratt wrote: > Hi. I am creating methods for form validation. Each validator has its > own method and there quite a number of these. For each field, I want > to evaluate errors using one or more validators so I want to execute > the appropriate validator methods from those available. I am iterating > over each validator using validateField method to gather my results. It > works but it ugly and inefficient. Can someone advise whether there is > a better way of doing this. I realize that the validator variable in > my iteration is only a string so question is how can I make the > validator string reference a function so I may be able to shorten > validateField to something similar to this (instead of my long list of > ifs which I am not very happy with): > > for validator in validators_list: > result = validator(name, value) > if type (result) in StringTypes: > results[name] = result > > Many thanks > David > > My current situation below: > > # A large list of validators > def isDecimal(name, value): > """ Test whether numeric value is a decimal """ > result = validateRegex(name, > value, > r'^([+-]?)(?=\d|\.\d)\d*(\.\d*)?([Ee]([+-]?\d+))?$', > errmsg='is not a decimal number.', > ignore=None) > return result > > def isZipCode(name, value): > """ Tests if field value is a US Zip Code """ > result = validateRegex(name, > value, > r'^(\d{5}|\d{9})$', > errmsg='is not a valid zip code.', > ignore=None) > return result > > ... more validators > > # Iterating over validators to gather field errors > def validateField(name, value, validators_list, range=None, > valid_values=None): > """ Validates field input """ > results={} > for validator in validators_list: > if validator == 'isContainedIn': > result = isContainedIn(name, value) > if type (result) in StringTypes: > more... > if validator == 'isDate': > result = isDate(name, value) > if type (result) in StringTypes: > more... > if validator == 'isDecimal': > result = isDecimal(name, value) > if type (result) in StringTypes: > more... > > more validators ...
That's a typical case for using an OO approach; just make a class for each validator and have a single polymorphic validate method (I would make validators __call__able instead of naming the method 'validate'): # Abstract Validator class; not strictly necessary but good for documentation class Validator(object): def __call__(self,field,value): '''Validate a value for this field. Return a string representation of value on success, or None on failure. ''' raise NotImplementedError("Abstract method") class DecimalValidator(Validator): def __call__(self,name,value): '''Test whether numeric value is a decimal.''' class ZipCodeValidator(Validator): def __call__(self,name,value): '''Test if value is a US Zip Code.''' def validateField(name, value, validators): """ Validates field input """ results = {} for validate in validators: result = validate(name,value) if result is not None: results[name] = result # XXX: if more than one validators succeed, # all but the last result will be overwritten return results # test validators = [DecimalValidator(), ZipCodeValidator()] print validateField("home ZIP", "94303", validators) Regards, George -- http://mail.python.org/mailman/listinfo/python-list