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.