Building Data-Driven Web Apps with Pyramid and SQLAlchemy Transcripts
Chapter: Client and server-side validation
Lecture: Server-side data exchange

Login or purchase this course to watch this video and the rest of the course contents.
0:00 I feel like we kind of made a mess and we actually skipped over some important stuff in the previous chapter when we talked about forms and user input.
0:09 We didn't do all the validation that we should have and, we kind of made a mess while doing it only partially.
0:15 So we're going to do some dramatic clean up using a design patern called view models. Let's just jump right into it and see it in action
0:23 and then we'll come back and review the concepts. We're on to a new chapter so that means on to a new section
0:29 in our GitHub repository. So Chapter 13 validation final of course starter is the same but right now, but final is going to be
0:37 whatever we do in this chapter. These numbers are of course subject to potentially changing as we evolve the course, but for now Chapter 13.
0:46 I've already setup all the virtual environments and stuff for here, let's open it up and get going.
0:51 So let's start by looking over in the AccountController. That's probably the dirtiest or messiest on this little auto import stuff up here.
1:02 I kind of got stuff sorted out of order, but here we go. So even when we are just trying to show the homepage
1:08 we do have to pass the user but we also have to pass this user ID. Remember we have to constantly get that from the cookie_auth
1:16 here to pull it back, but even down here we're passing it. We're going to pass all this extra data when we're even just showing the form.
1:24 So what we're going to do is we're going to create these things called view models. See, they're just classes, and the classes are
1:30 deeply tied to the data that's exchanged by this method and the data contained in the HTML. So we know there is a form and register
1:41 that is going to exchange that data. And we know the layout, the shared layout, needs that data. So what we're going to do
1:48 is we're going to bundle that up into a class. So we sort of keep the class in sync with the data in the validation and all that checking stuff
1:56 is going to go into that class as well. There are a lot of these things and they're like I say very much tied to the things being exchanged here.
2:08 So just like we did with templates we created some for account, we created some for the home and so on.
2:14 We're going to do the same thing for view models. It's going to have a similar although, not exactly identical, structure.
2:20 So let's come over here and create a sub-package called view_models and in here I'm going to create a directory called shared
2:31 and let's do one for account. So as you might guess from these names there's going to be a base class that has lots of stuff that is shared like almost
2:39 everything needs this error and absolutely everything needs user_id. So that kind of stuff is going to go in there
2:47 as well as the ability to take an arbitrary in memory class and convert it to a dictionary which is what's required in the web framework.
2:55 So let's start here. Create a thing called view_modelbase and we'll create a class called ViewModelBase
3:05 and this is going to be the base class of all of the other view models. And it's going to have two important things.
3:11 It's going to come in here and it's going to take the request and of course, let's go ahead and type that so things work a little nicer
3:18 and it's going to come here and it's going to say sel.request. Just go ahead and hang onto this because sometimes the derived classes will need it.
3:26 And, let's go ahead and set that error which is a str to None. So this means any of the forums that have errors
3:36 it's just it's not everything using this but it's so super common that we're going to just put it here. We'll say self.user_id. And this is an int.
3:47 And for a second I'll say None. Alright, so these shared pieces of data are going to be now available everywhere.
3:54 Well that's the storing the common data and how do we return this to a dictionary? Well let's just say create a function called to_dict
4:05 and it's just going to take the attributes or fields here that we're setting which actually go into an internal dictionary for this class.
4:13 I'm just going to return those. Say self__dict__. Alright, we can override this in base classes. For more complicated things, but, here we are.
4:22 So let's actually do a few more things. Here, we'll say self.equestdict, remember this thing? It's going to be requestdict, going to import that
4:31 .create_from_request. Let's go actually go to our cookie_auth and we're going to say, try to get the user ID from the cookie.
4:45 Maybe it doesn't exist, maybe it's messed with might be None, but if it's not, let's store it. Okay, so this is the shared bits.
4:54 And everything is going to derive from that. Let's go over here and create an AccountHomeViewModel.
5:07 So AccountHomeViewModel, it derives from this, whoops. No, it derives from this, which we have to import.
5:15 Takes an init, it has a request, which is a request. And, we have to make sure that we call super() init with the request before we do anything else.
5:28 Now, let's go back here on this home thing on the details let's do this one first. What other information do we have to do?
5:37 Well, we're going to actually pass the user along as well. Alright, we're actually getting the user and we're
5:42 trying to show it, so the user is included. Let's roll that in here. After this, we'll say self.user maybe with a little more space.
5:51 self.user = UserService.find_user_by_id(self.user_id) Look how slick that is. Okay, and let's just make sure this can take None.
6:07 Yeah, if it's none it will just come back with nothing, great. So, let's go re-envision this method now much cleaner with view models.
6:15 So we'll say vm = AccountHomeViewModel() we're going to pass a request we don't need this stuff, we just say look, if there's no vm.user
6:29 we got to get out of here. Otherwise, or turn vm.to_dict(). Now, this one didn't get that cleaned up but the more validation, and the more complicated
6:39 the data exchange, the better and better this gets. Let's just see that our account page works. Let's go over here, we may have to log in, nope.
6:48 Click on our account page, oh look at that. Account is here, whether or not we're logged in is here
6:52 the user was found, all of that, completely isolated. So what we get is these view methods that our super focused on orchestrating what has to happen.
7:03 They're not down in the nitty gritty details. So, that one was pretty nice. Let's do one about register. We're going to create a couple of these
7:14 so I think what I'll do is I'll just talk through this one more time and then we'll go quick for the rest. All of them are ViewModelBase derive.
7:24 They all have an init. That takes a request. They all call super, like that. Thank you PyCharm, and then they add additional data.
7:37 So let's go look over here, and copy this to get started. Let's go over here and see what we need. Well, we need, let's go like this.
7:50 Import that real quick and we're going to say return vm.to_dict(). What else do we need? We have user_id, and we have error, common.
7:57 But these three things have to come along. So let's just cut them to sort of remind us what we got to put here.
8:03 So we're going to have self.email = None So, here's those three pieces of data and now, that comes super nice and clean.


Talk Python's Mastodon Michael Kennedy's Mastodon