Validating a field multiple times with different @validates decorators is causing them to be skipped
If a field has multiple @validates decorators it will not consistently validate each of them properly and cause subsequent @validates to be skipped.
Example: the second validator, validate_field_positive_number, will not get run.
@validates('email')
def validate_test_123(self, key, field):
return field
@validates('email')
def validate_field_positive_number(self, key, field):
if True:
raise ValidationError('failed multiple validation')
return field
If you run it the first time. Validation will pass. If you remove/delete the validate_test_123 decorator and validation, the second one will always work.
The problem with this is that with a larger data model it's very clean to create generic @validates decorators for things like missing required fields, data types, etc. So having multiple @validates for the same fields is needed.
Thanks, Steve
Comments (8)
-
reporter -
reporter - edited description
-
repo owner hello -
This is not a documented behavior so I think this would be an enhancement. However, I don't see how it can work. One @validates is likely to be dependent on the other, because if validator A changes the value in some way, validator B will often be dependent on that change having taken place or not. It follows then that the validators would need to be called in a specific order. However, how would this order be determined? We would only have access here to perhaps the order in which @validates() was called. But if you arranged your classes differently or even the order of imports changed, this would break. This seems quite brittle. So I'm not sure if this feature is feasible.
-
repo owner - changed component to orm
- marked as enhancement
-
reporter Hi Michael,
Thanks for the quick response. The validators I've been using are not changing data, but instead just ensuring the value/structures are in the format I'd require. I see your point if the validators are changing the data that could then become an issue.
Just thinking that there could be two different types of validators. One for immutable and one for mutable. Multiple validators for immutable: @validates_chain Single validator for mutable. @validates
I guess I find it kind of messy having to repeat the same validation code in multiple @validates for various fields but if this is by design, then I'm happy to go with it. I'm really loving SQLalchemy.
I might create a PR to update the docs (http://docs.sqlalchemy.org/en/latest/orm/mapped_attributes.html#simple-validators) so this becomes more visible, so others don't try to also use multiple @validates for a single field.
-
repo owner we can make it raise for conflicting @validators. that might be more self-documenting.
-
repo owner -
repo owner - changed status to resolved
Raise when two validators conflict
Two @validates decorators that make use of the same name is not supported. Raise an exception.
Change-Id: Ia3e89ffdc9ef345a0de258e2ac0ac5e0bd421c61 Fixes:
#3776→ <<cset 117997cd5b84>>
- Log in to comment
SQLAlchemy==1.0.12 Also using Flask and Flask-SQLAlchemy==2.1 but having a feeling this is a core issue.