Eve: Building RESTful APIs with MongoDB and Flask Transcripts
Chapter: Schema definitions and validation
Lecture: Advanced validation rules
0:01 I want to show you a few more rules, and the first one is going to be coerce.
0:05 With coerce, you can pass a callable, and a callable will be applied
0:09 to the value coming into the field,
0:12 and the return value of your callable will be used to update the field
0:17 before validation is performed on the document.
0:19 So, here I updated my age field,
0:22 it isn't a read-only field anymore, now it is a writable integer,
0:27 but we're also applying a coerce rule
0:30 and the callable we choose to use here is int,
0:35 so we're converting the value of the field to an integer, if it isn't already.
0:40 Let's see this one in action.
0:42 So we have this person here, Mr. Roger Federer,
0:46 he lives in New York, and he is very young, he has an age of 18,
0:51 but as you can see, I am passing a string here
0:54 while age is supposed to be an integer.
0:57 So normally, we will get an error when we try to save this guy
1:01 because the type is not the correct one, the expected one,
1:06 but let's see what happens when we post Roger Federer to our API.
1:11 As you can see, we get a created, no errors,
1:14 and we inspect the values of this document,
1:18 we see that the first name, last name, location and age
1:22 have been converted to an integer for us.
1:24 And also you can use an iterable here in your coerce rule,
1:30 if you do that, any function you provide
1:35 within your iterable will be applied in sequence.
1:39 So in this case, first we will get an integer conversion applied to the value,
1:43 then the result, the return value of this conversion
1:47 will be passed to the next function, which in this case is a string conversion
1:52 it doesn't make any sense, it is going to get an error to us,
1:55 let's go back to hit this error again, but you get the point.
1:59 Another powerful rule I want to show you is regex,
2:04 what it does is pretty obvious I think,
2:07 it allows you to the final regular expression
2:10 and the value coming into the field will be matched against the expression
2:14 and only if it passes validation against the expression, it will be accepted
2:20 so let's go back to Postman, I have my email field here
2:24 and I am passing a string, it is a valid string but not a valid email.
2:30 If I try to send this person to the API I get an error,
2:34 email does not match the regular expression.
2:37 Now if I go and fix my expression,
2:42 I should get a green light, exactly,
2:46 so now I have my email validated, correctly, as expected.
2:52 Another use for rule is dependencies.
2:55 This is very common here I have one field which is dependent on others
3:00 So here I added a middle name field
3:03 and it depends on first name and last name
3:05 which means that the field itself is not required.
3:08 In fact, there is no required rule, but if you provide a middle name,
3:13 you also must provide the first name and last time,
3:16 otherwise, the field would be rejected.
3:19 You can also have only one dependency of course,
3:21 in this case, you can just pass a string with the field name
3:24 without the need of full list.
3:27 So let's, try this one, super simple, we have Scott Fitzgerald,
3:32 we try to send this one off and we get an error
3:36 because there is an error in the Json, yes,
3:39 we're missing a comma here, let's try again.
3:43 As you can see me, middle name field, the first name is required
3:47 if we add the first name which is the second required field
3:52 for middle name to be accepted, we get the created message.
3:59 So dependencies, you can have more than one field
4:03 if you have more than one you need a list, otherwise the string
4:06 and another nice feature is that .notation is supported,
4:10 so suppose that you want middle name
4:13 to be dependent on location.address for example,
4:17 which means that not only first name and last name,
4:21 but also location which as you might remember is a sub document.address
4:29 must be present in order for middle name to be accepted.
4:34 Another set of rules I want you to know about is what we call the *of rules.
4:41 This is a family of rules, actually, you have different variations,
4:45 so you have all of, any of, non of, one of
4:50 and what these rules do is
4:53 they allow you to list multiple sets of rules to validate against.
4:58 Let's see an example, here I have a property which is called prop 1
5:05 and the type is number, so both integer and floats will be accepted
5:11 but I want to accept numbers which are in a range between 0 and 10
5:16 or in a range between 100 and 110.
5:21 I don't want to accept 50 for example,
5:23 which isn't included in any of these two ranges.
5:26 So what I am going to use is any of
5:28 so at least one rule in this iterable must be valid
5:32 in order for the value in this field to be accepted.
5:36 The rules, as you can see, are defined as dictionaries,
5:38 here is the first rule and then we have the second rule.
5:43 Let's go to Postman and try this out, prop 1 is 50,
5:49 as you can see for field prop 1 we have an issue
5:52 and the issue is that no definitions were validated.
5:57 The first one is not valid because the max value is 10 while we provided 50
6:02 the second rule is not met because the minimum value is 100
6:07 and again, we provided 50.
6:11 So depending on your necessity,
6:13 you can pick the most appropriate of these rules,
6:16 for example, if you don't want any of the schemas to be valid,
6:22 then you can use none of,
6:25 and another interesting one is one of
6:28 which validates if exactly one of the provided constraints applies.
6:34 Another interesting feature of these rules is
6:38 that they allow you what we call a type saver.
6:43 So, for example, here we are defining a foo field
6:47 which has a rule anyof_type and then we pass a list of types
6:54 so string and integer, this is equivalent to
6:57 doing foo anyof_type string as a first constraint and type it as a second constraint
7:06 so let's go back to our number definition here.
7:11 I could replace this with anyof_type integer string,
7:24 it doesn't really make a lot of sense
7:27 because we already have the number shortcut for doing this,
7:31 but it is useful to know that you can do this kind of stuff
7:34 because it allows you to shorthand most of the rules
7:38 And when you have a lot of rules in your schema, it can come in handy.