Reputation: 2711
I know i can setup a validator on a Model's column using, according to the SQLAlchemy documenation:
def validate_phone(target, value, oldvalue, initiator):
"Strip non-numeric characters from a phone number"
return re.sub(r'(?![0-9])', '', value)
# setup listener on UserContact.phone attribute, instructing
# it to use the return value
listen(UserContact.phone, 'set', validate_phone, retval=True)
But i want to pass extra arguments to the validator for example:
def check_range(target, value, oldvalue, initiator, begin, end)
if value in range(begin, end):
return value
else:
raise ValidationError()
How must i configure this validator in the listener so that it will accept the extra arguments begin and end?
Upvotes: 0
Views: 536
Reputation: 2711
OK, i solved it by adding a parameter to my Column definition (i had already defined an RsColumn class which inherited from Column to add extra arguments) which contains a dict with validator-function-names and optional arguments as kwargs.
When my application starts it parses all the Models and checks if there are custom validators defined on a column in the
validators=[
{
"function": "myvalidatorname",
"kwargs": {"arg1": 1, "args": "someotherargument"}
},
{ ... }
]
-argument in the column. It sets a listener on "set" which executes the function "execute_field_validations" which again parses all the "validators" in the field and executes them optionally with arguments if they are given.
def check_positive(value, field):
# do stuff
pass
def check_range(value, field, begin, end):
# do range checking
pass
def execute_field_validations(model_instance, value, old_value, initiator):
"""
When a "set" event is given on a models field/column then execute
all the fields validators optionally with arguments as described
in the model's definition in db.models
for example VehicleType.loading_meters:
loading_meters = RsColumn(..., validators=[
{"function": "check_positive"},
{"function": "check_range", "kwargs": {"begin": 0, "end": 1000}}
], ...)
"""
field = model_instance.__mapper__.columns[initiator.key]
for validator in field.validators:
try:
assert validator["function"] in globals(), \
"Invalid validator '{0}' in column ".format(
validator["function"]
)
validator_function = globals()[validator["function"]]
if "kwargs" in validator:
validator_function(value, field, **validator["kwargs"])
else:
validator_function(value, field)
except Exception as e:
raise ValueError()
def configure_validators_on_individual_fields(base):
"""
Parse through all models and all defined columns/fields
and see if there are individual validators set on them.
If so add a listser for them on the "set"-event
"""
for table in base.metadata.tables:
for field in base.metadata.tables[table].columns:
if field.validators:
listen(
getattr(
get_class_by_tablename(table),
field.name
),
"set",
execute_field_validations
)
Upvotes: 1