Eve: Building RESTful APIs with MongoDB and Flask Transcripts
Chapter: Schema definitions and validation
Lecture: Custom rules and types
0:00 We already learned that Eve offers a wide and flexible range
0:04 of validation and transformation rules.
0:06 No matter how powerful and rich a validation system is,
0:09 there will always come a moment when you need to go beyond that.
0:14 This is the case when you want to validate a value
0:18 that must conform to standards and conventions,
0:21 which are specific to a certain application field.
0:25 Eve allows to extend the validation system by creating custom rules,
0:30 adding in new types or using validating functions.
0:34 In this lecture, we're going to see how we can work with these features
0:38 to unleash the full power of Eve validation system
0:41 and model it to suit our own specific needs.
0:44 Now, if you look back at our app.py script
0:49 we realize that we haven't really been working on it for a good while
0:54 most of our time is being spent on the settings file
0:58 and this is nice because we've been changing
1:01 how our service responds to requests updating its schema
1:06 endpoint configuration, everything we've done it's been always a declarative thing,
1:12 we just updated our settings files,
1:14 but now that we want to extend the validation system features set
1:19 we need to write some code, and this is probably very exciting.
1:22 So let's start by important from eve.io.mongo
1:33 as you can see, the eve.io.mongo name space
1:38 exposes a validator class, this is the class used by Eve by default.
1:44 And you see, it is stored within the Mongo name space,
1:48 which already hints at the fact that
1:51 you can have probably more than one validator
1:55 maybe a SQL data layer will be using its own validator,
1:58 which makes sense if you think about it.
2:01 Now that we have a validator class, we want to subclass it.
2:07 Let me save these, as you can see, the server has restarted here,
2:11 and how do I use my validator to replace the standard one,
2:16 well, this is super easy, all I have to do is pass it to my instance.
2:27 So this is how I replace the standard validator
2:32 coming in this case with the Mongo data layer with a custom one,
2:37 right now we aren't really doing anything,
2:40 my validator here is exactly the same as the in-house validator, so to speak.
2:45 Let's, see how we can improve on it.
2:48 Just for fun, let's assume that we're really interested
2:51 in only accepting odd numbers for a certain field,
2:54 and we want to build a custom rule for that.
2:56 We want to be able to go to our settings file,
3:00 pick our age field here and say,
3:04 yes, it is an integer, but look, we also want this integer to be odd.
3:13 So we want the rule like this one is odd true,
3:18 which means age must be an odd integer,
3:23 let's just get rid of this coerce function here just to avoid confusion.
3:27 Let's, go back and let me paste the code for this validation,
3:34 here it is, so as you can see, the way you create a new rule,
3:39 is defining a private function, you can tell it is a private one
3:43 because it has this underscore at the beginning,
3:46 which is a convention in Python for private functions within a class.
3:49 And then you have the validate keyword,
3:51 and then another underscore and then actuall rule name
3:57 so validate is odd. Of course it is a class function,
4:00 we're accepting this is odd, which is a boolean,
4:04 and then the field and value for the field
4:07 which we have to validate against.
4:10 Implementation is very simple, it is just the test
4:12 if the number must be actually odd and it isn't, then set an error.
4:18 So here you see how you set an error,
4:20 you just invoke the error method you pass the field
4:23 and the description for the error, and that's it.
4:28 So let's save, server restarts,
4:32 and let's go to Postmen and see what we've done.
4:35 So here I'm posting last name and age,
4:39 last name I'm adding it because it is required if you remember
4:42 and age is 18, let's try to post this.
4:47 And we get an error, unprocessable entity,
4:49 and as you can see, age value must be an odd number.
4:54 Let's try with 19— good.
5:01 We now know how we can define custom rules
5:04 and apply them to whatever field we need.
5:06 But what if we want to the define custom types instead?
5:11 Let's go to our settings file and look at this email field.
5:15 It is a string and we are applying our regular expressions rule against it,
5:20 it works fine, but if we had more email fields,
5:23 and maybe in other endpoints in our service,
5:27 every time we'd need to copy and paste all this stuff here
5:30 which is also prone to errors,
5:32 it would be much better if we could define a type email
5:36 this way we would not need to type any regular expressions
5:40 and our type would be reusable anywhere
5:44 even in different services in our microservices network maybe.
5:50 We can do that, let me save this type definition and go back to our app.
5:54 The way we define a custom type
5:58 is very similar to how we define a custom rule,
6:02 _validate type,
6:06 now the intellisense here is already hinting at how the Mongo validator
6:12 is extending the base validator class
6:15 as you can see all these types here are Mongo types,
6:20 So let's define our email as a class method,
6:32 this is how you define a custom type, let me paste the actual code.
6:37 So if the regular expression is not matched, then set the field error.
6:44 Now, before we say we need to import regular expression module,
6:50 let me save, relaunch.
6:57 Now, if we try this post here, email should be a type,
7:05 you see we get value is not a valid email for the email field.
7:09 Let me try with a valid email.
7:13 Great, back to our editor,
7:18 So here is our code, as you can see,
7:20 a simple class, subclassing the Mongo validator,
7:23 and you can define custom rules or custom types,
7:27 and these are reusable, you can import your specialized class
7:33 whenever you need to,
7:34 If you're building multiple services with Eve,
7:37 you can reuse your class in all of these services
7:41 which is interesting if you're building a micro services network.
7:45 And the way you pass your validator to the Eve instance
7:49 is simply passing it when you instance the class as an argument.