RESTful and HTTP APIs in Pyramid Transcripts
Chapter: Validation with view models
Lecture: Adding validation to APIs (never trust input)
0:01 Let's come back to our auto API and make this a little bit more realistic;
0:05 so it looks like we've got a renderer stuff
0:08 working really well with the negotiate stuff,
0:11 I think we've got the restful components working great with our http verbs
0:14 our response status codes, things like that.
0:17 But, still not very realistic, so if we look here, I think this is solid
0:21 you ask for all the cars you get all the cars.
0:24 Here you ask for a particular one, and if it doesn't exist, you get a 404, great.
0:28 But the farther down we go, it gets the less good,
0:31 like notice this part about validation.
0:34 We're taking the arbitrary dictionary submitted as a json object
0:36 back to our view here, and then we're just going that's probably a good car.
0:40 No, that's probably not a good car, we should not be trusting user input here,
0:44 now to some degree in the database, when we get to the data layer,
0:48 we can model it such that certain types are required,
0:51 so for example the price must be a number, right
0:53 it can't be just anything, right or that the name is required
0:57 like these things can be modeled in database constraints.
1:00 We probably don't want to count on that, right if we count on the database
1:04 to actually be the validation layer, we're going to get like sqlalchemy errors
1:08 as the thing we tell them that went wrong, and that's not great
1:11 we'd much rather say hey, this number that you've submitted
1:16 has to be between this and this, right
1:18 this thing must be of this type, and so on,
1:20 so we need to add the validation and for a moment
1:22 I'm going to make this method worse, not better
1:25 by actually putting all the validation here,
1:28 because right now where does it go, right,
1:31 maybe, maybe it goes in from the car, right from dictionary bit that parses it
1:35 and that would not be a bad choice in this particular case,
1:38 we could put it there, we could have a different exception type that catches the errors
1:43 to me, let's just look at the car real quick.
1:45 The car is, it's really supposed to be the database object, right
1:49 it's suppose to know what it fields are and so on,
1:52 and so we model this in sqlalchemy,
1:54 it's really going to represent the sqlalchemy thing, so maybe even this
1:57 like we probably don't even want this year, so ideally we take this way
2:00 rather than leave it here, at a minimum we need to rewrite this
2:04 because it turns out if the dictionary contains something that's not listed here
2:08 it's going to crash, as well as if the dictionary omits something
2:12 like the price for example, it's going to crash as well.
2:15 So this needs some work, right and we could probably
2:19 move that out of the cars responsibility as well.
2:22 Let me just go and put some validation here we're going to leave this part in,
2:25 but for example we want to check that hey, the price is valid
2:30 we want to check that it has a name and things like that.
2:33 Now instead of me typing that all in, let me just paste a bunch of rules here
2:36 and let's do a little trick here, new car, let's rename this, back to car.
2:44 All right, so for example, what can we check,
2:48 let's suppose we want to be able to give more than one error,
2:50 like hey these three things were wrong with your submitted post, okay
2:54 so over here, we're going to say if you did not set the last scene,
3:00 like this is the date time value for what is supposed to be there,
3:04 that's required, that's an error, if you don't set the name, that's an error,
3:08 or if it's empty right, this will also test if it's empty.
3:11 If we want a check if it's only not there, like is none, right,
3:14 we could do something like this
3:16 if it were allowed to be empty but must be present,
3:18 but we'll just go like this, the brand has to be there, the price has to be set,
3:21 the price cannot be negative right,
3:24 you can't have people pay you to buy the car or whatever;
3:29 similarly, the year has to be a positive number
3:33 it's got to be reasonable like 1900 until present plus one year, things like that.
3:41 But you can see there's a decent amount of validation here
3:43 and I would contend that this is just part of it, this is only a little bit of it,
3:47 now like I said, the database will catch some things that are out of step
3:51 as well as when we parse it, we'll be able to do a little bit of work there as well.
3:55 But now let's just start to look at this method.
3:58 This is not amazing, right, I mean it's doing all this work
4:02 and we really just wanted to kind of do this, this is sort of the point,
4:05 but so much other stuff going on that it's obscured by that
4:09 so what we're going to do in this chapter is
4:13 we're going to add another layer that's at play here,
4:16 so something I'm going to call view models
4:19 and the role of these view models will be to take the inbound data
4:22 whatever that means, right, like this if it comes off of the url
4:25 that's also a part of it, we could take those things together
4:29 and do the parsing and the validation and all of that
4:33 and provide kind of the final result to this method
4:37 to do whatever it's going to do with it right,
4:39 like then hand it off to the repository, and things like this.
4:42 And that makes it much easier to test, we can test the validation
4:45 by testing the view models, it will make our APIs much cleaner
4:48 by having one concise common clear repeatable way to do validation
4:53 and if we want to add— I would at some point get tempted to go
4:58 okay no more validation, it's just making this a mess
5:01 and I don't want this method to be like only validation,
5:04 alright, but if you move that validation somewhere else,
5:07 well then you can go crazy and put all sorts of rules over there
5:09 and it doesn't clutter up the reading of the code.