New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Voluptuous cannot support multi-field validation #124
Comments
Yes, this is definitely a limitation of Voluptuous. I haven't come up with a good design solution, but I'd be interested in adding it if something elegant presented itself. |
The most obvious way to me would be to introduce the concept of events, and have an def passwords_match(values):
if values['password'] != values['confirm_password']:
raise Invalid(...)
s = Schema(...)
s.on('after_validate', passwords_match) Or you could use inheritance: class SignupSchema(Schema):
def after_validate(self, values):
if values['password'] != values['confirm_password']:
raise Invalid(...)
s = SignupSchema(...) # same constructor |
Can't this be done trivially with def passwords_must_match(passwords):
if passwords['password'] != passwords['password_again']:
raise Invalid('passwords must match')
return passwords
s=Schema(All(
{'password':str, 'password_again':str},
passwords_must_match
))
# valid
s({'password':'123', 'password_again':'123'})
# raises MultipleInvalid: passwords must match
s({'password':'123', 'password_again':'and now for something completely different'}) This leads to a reasonably clean pattern where you use Extending a little further to the password length-checking case: def password_min_length(passwords):
if len(passwords['password']) < passwords['min_length']:
raise Invalid('password should be at least {} characters'.format(passwords['min_length']))
return passwords
s2=Schema(All(
{'password':str, 'password_again':str, 'min_length':int},
passwords_must_match,
password_min_length
))
# MultipleInvalid: password should be at least 5 characters
s2({'password':'123', 'password_again':'123', 'min_length': 5}) |
@thatneat: 👍 :-) |
@thatneat I had the same need (to compare start/end dates in a schema), and used |
Yeah, that is a limitation of this approach. I think it's actually a good thing in the cases I've seen - for instance, it means that your I suppose you could write a different version of |
Yeah, this is true... in a theoretically multi-field API it could be in |
Ah, I see, do you have other fields as well that shouldn't affect whether the s=Schema(All(
{'password': str, 'password_again': str, 'totally_unrelated': int},
passwords_must_match
))
# Ideally, this would be MultipleInvalid:
# passwords don't match _and_ 'totally_unrelated' should be a number.
# Instead, you just get the 'totally_unrelated' error and it looks like the passwords are fine.
s({
'password': 'abc',
'password_again': 'does not match',
'totally_unrelated': 'not a number'
}) I agree that there doesn't seem to be a way to do that well. Would the alternative version of |
In your example the chaining isn't necessary. With date comparisons, if |
I should have asked this earlier, but could you provide an illustrative example of what's wrong and what your ideal interface would be? |
Sorry I never got to this, the project I was using voluptuous on is no longer active. |
Shouldn't |
Hi @alecthomas, it looks like Voluptuous is not super active, but I thought I'd raise an architectural point with you. It seems like there's no way to write a validation which depends on the value of another field. For example, there's no way to require that a field called
password
andconfirm_password
actually match. Or that a field calledsize
actually refers to a size that is in stock for the product referenced byproduct_id
.Am I wrong, and if so, how would I do those kinds of validations? If not, are there any plans to support them?
The text was updated successfully, but these errors were encountered: