Building Data-Driven Web Apps with Pyramid and SQLAlchemy Transcripts
Chapter: Course conclusion
Lecture: Core concepts reviewed
0:00 The first core concept that we talk about were just the building blocks Pyramid. We saw that Pyramid was built upon routes
0:09 which map URLs to a view method sometimes called action methods. We have templates, like Chameleon templates
0:16 that we take and pass models from our view methods down to the templates. And the templates then take that
0:22 and generate HTML, the templates are basically dynamic HTML. And then we added a bunch of our own layers.
0:29 We added the concept of view models and data services. And all of this organization that allowed us to evolve our web application super, super easy.
0:38 These are just some of the core building blocks of Pyramid and our web application. We saw there are two powerful ways
0:45 to create your Pyramid app, at least two right. There's always more than, more than you might expect. One really simple out of the box was
0:54 is to use PyCharm and its tools to create Pyramid web applications. The other one is that we could use CookieCutter
1:01 and the command line to create them. I guess another, you could just start from empty files and start typing but that seems
1:07 like you're wasting your time. So when I was new I found I used the PyCharm way a lot. It made me feel real comfortable.
1:13 And it was like super easy to get started. And the more I get into it and the, as the years have gone by I much prefer to do the command line stuff
1:22 and then finally edit in PyCharm. But not create in PyCharm. You will find maybe that right now one thing is the right solution.
1:29 And then later as you get more experience there might be something else that is a different better solution.
1:35 There are many different types of templates. We have at a minimum Jinga 2, Maco, and Chameleon. We saw that Chameleon is the most web like.
1:43 With the least extra syntax. And so I awarded it this little blue trophy and said, this is the best way because this is still proper HTML.
1:55 Where all of the other template languages are madly broken HTML with lots of open begin this, end that, end if, end for sort of stuff.
2:03 And to me that's just, I just don't like typing that stuff. And I don't like the fact it's not proper HTML. Pyramid supports all three.
2:11 We use Chameleon and I encourage you to make those decisions for yourself and think through the trade offs. Closely related to Chameleon was this idea
2:21 of a core layout template. Now this exists in Jinga, Maco, and Chameleon. And whichever template language you use it's really important that you create
2:29 one of these layout templates that's going to drive the overall look and feel of your site your navigation
2:43 Here you can see the Talk Python to Me podcast website. Although there are many pages here the home page, the episodes page
2:49 and the individual episode details they all have this very structured common look and feel and that's done by the layout template in Chameleon.
2:58 One of the really important things we focused on in the beginning was routes. Typically we have some kind of static route
3:11 URLs, to their implementation in our web app. So we might want to have / go somewhere. And that's pretty much required for a website.
3:19 And then we might want to have /help. or /project/package. These can be static like the first two. Or it can pass data in the URL like the package one.
3:28 And we can even put predicates and constraints. So we said, we'd like to be able to just say /7, and have that look up
3:37 which is the seventh most popular package. It's kind of a silly idea. But that's what we did. We can do that by having this little
3:43 lambda function which is a test. Is that thing a number? Well this route is only going to match then.
3:49 Now remember, there's an order of operations here. We must have the most specific first and the most general stuff at the end.
3:57 The way this works, think of Pyramid just taking a URL and running it from top to bottom through this list the first one that matches, that's it.
4:04 So if you have some super broad thing at the beginning well the stuff below it will never hit. So very very specific stuff at the beginning
4:12 working your way down to more general. We saw that Bootstrap allows us to make our design much better.
4:20 The CookieCutter templates already come with Bootstrap which would take us from the really bad page to the middle page, which is already better.
4:28 And then we can use themes and some of the other Bootstrap elements like buttons and nav bars and so on to get a really nice page.
4:35 Be sure to take advantage of what Bootstrap and its theme ecosystem has to offer for you. With our design in place, it was time to write
4:43 some database access code. We wanted to work with a relational database for most of this course, so we were using SQLAlchemy.
4:51 SQLAlchemy has this concept of a unit of work. And that is embodied in this thing here we're calling s, a session.
4:58 So we use the session to create the queries. Also to do the inserts and deletes and commit the changes.
5:04 Here we're not committing any changes so that's fine. But we write this query against our models in this case an account that has an email
5:10 and a password hash. And then SQLAlchemy's job is to generate the SQL targeted at the database we're talking to.
5:18 If you're talking to Oracle, generate it one way. If you're talking to SQLite generate maybe different SQL statements.
5:25 Which would still be different than say Microsoft SQL Server. And you can see down on the bottom
5:29 it writes more or less the SQL code that you would write. Select star from account where these values are equal to this.
5:35 And it uses a parametrized query which is really really nice. Relational databases are nice, until their not. And one of the times they're not nice
5:43 is when you have to evolve from one shape to another. We saw SQLAlchemy really hates that. Queries themselves Don't work very well unless you evolve
5:53 those types of things. If we're already using SQLAlchemy we might as well use Alembic, which can automatically generate the sequel statements
6:00 and sequel operations to transform from an old database with an old set of models to a new database matching the current models.
6:08 So Alembic allows us to do what are called migrations. And this is super important for evolving our application and our database structure
6:16 once SQLAlchemy has created it. When we are accepting user input we use the get post redirect pattern. The idea is the user gets some form.
6:27 They edit it locally. They post that data back. We save it to the database. And then we redirect them somewhere else.
6:34 The redirect is really nice because now they're in this new location and if they refresh the page
6:39 that's fine, it just keeps showing them that new stuff. As opposed to, this form has been submitted. Are you sure you want to submit it again?
6:46 And those kind of weird things. So it's a really nice and clean workflow for accepting user input in web applications.
6:53 As we accept user input, we have to do things like validation, and data exchange and all of that. And we came up with this concept of the view model
7:01 which handles mapping the data from the HTML into Python's memory and validating it. That doesn't sound like a big deal.
7:08 But that turns out to be a massive amount of what we would otherwise put inside these action methods. And it makes it real easy to test
7:15 this validation and data exchange. And it really simplified our action methods and lets it focus on orchestrating the steps
7:21 and doing the high level stuff. And our view model can do all of the nitty gritty data exchange and conversion. Speaking of testing
7:28 we focused on three types of tests that I consider to be somewhat unique to the web. And we talked about how to do this in Pyramid.
7:36 Of course there's many types of tests. One of the tests that we might want to do is this data exchange and validation.
7:41 And in our world that means testing the view model. And that means passing a real true request object from Pyramid on to the view model
7:49 so it can interact with all of the various dictionaries and other data exchange mechanisms. We can use webtest to create these dummy requests
7:57 and even pre-populate them with data to test various scenarios. We could do that for the view model. We could do that for the view method
8:05 which may or may not use a view model. Or we could entirely start up the entire web application and pass fake web requests to it.
8:13 So we talked about the three levels of tests. And then like I said there are others in testing in general.
8:19 But these are pretty relevant to the tools and techniques that come along with Pyramid and WebTest and things like that.
8:26 Once we wrote our app, we tested our app. It was up and working. Then we decided to deploy it to a Linux server in the cloud.
8:33 So we used Nginx, which was the front end web server. The request came into Nginx. That's probably HTPS and get static files and stuff like that.
8:42 But when there was a logic based request like show me this package we need to run our Python code. So those requests would flow on through uWSGI
8:51 which is running in this sort of master emperor mode. And there's a bunch of worker processes where our Python code actually runs.
8:57 And uWSGI figures out which one to pass off the request to. And then flows it back in reverse through this whole thing.
9:04 So you have a bunch of scripts that set this up. And we went through it. And it should be pretty straight forward
9:08 to get it working with that all in place. The last thing we did is said let's change databases. That seems like a good idea
9:15 now that we've done all this work. Well, there was two ideas here. One, we wanted to say well maybe some people want to use MongoDB, and NoSQL.
9:23 And actually our relational database and our NoSQL database were much closer than people might realize 'cause we could use SQLAlchemy and Mongo Engine
9:31 and those are quite similar to those things. Not the same. One is active record. One is unit of work. Things like that. But not terribly different.
9:38 It was a pretty small amount of effort to considering the type of changes we made. So we switched to MongoDB.
9:44 And that was maybe interesting in its own right. It's also interesting in showing the power of what we had built up to this point.
9:51 We only had to change the data services obviously new entities, and a few very minor things. Like we had to change the type of value exchange
10:00 for the user cookie 'cause one was a BSON object ID and the other was an integer. And those are obviously not the same thing.
10:06 So there's a little bit of work in the cookie level to make that change. Other than that, our design patterns really isolated the types of changes
10:14 to the locations that we, well want them to be. Data changes and the data services for example.
10:19 So hopefully you found that really interesting and powerful. And the main takeaway I wanted you to get was we don't have to be stuck with how
10:28 we started building our app. It's actually if we build it correctly quite easy to transform and change from one style to another.
10:35 This database change is just one of those types of changes that we prepared ourselves for by clearly and nicely structuring our code. Well that's it.
10:45 Those are the major concepts of what we covered in this course. I hope you feel like you learned a lot. And I hope this quick review helps them stick.