Building data-driven web apps with Flask and SQLAlchemy Transcripts
Chapter: Routing and URLs
Lecture: Refactoring view methods with Flask blueprints
0:00 So here we are in our Flask app.
0:02 And it's pretty standard, right?
0:04 This is like how they tell you how to do it in Flask.
0:06 Import flask, you create your app
0:09 and then you create your view methods.
0:10 You put your app.route on them.
0:12 Well, okay, that's how you get started maybe sometimes.
0:16 But this is a terrible way
0:17 to organize real applications.
0:20 It definitely encourages just cramming
0:22 your entire web app into like a single file.
0:26 Bad idea. And it's bad because Flask has a really
0:29 super cool way of organizing your views
0:32 that you don't have to do much at all about.
0:34 You just change basically a one word right there
0:37 and you're good to go.
0:38 So what we're going to do in this little short segment
0:41 is we're going to reorganize our code
0:43 not because it's really that long
0:45 you can see it's actually short
0:46 but so that it's ready to grow
0:48 as we build up this real application.
0:51 So let's do a couple of things.
0:53 The first thing I want to do
0:54 is actually deal with this fake data.
0:56 We're going to have a real database
0:57 with lots of interesting stuff going on.
0:59 So I want to create a special part
1:01 of my application just for that.
1:04 I'm going to call that services.
1:07 Not web services, but services that are provided
1:09 through our application like stuff that deals with packages
1:12 stuff that deals with users, and so on
1:14 so we can isolate that over here.
1:16 So I'm going to create something called
1:19 package_service. Like so.
1:23 And then let's just take this code and put it over here.
1:27 All right. Not super interesting.
1:29 Remember, we don't have our data yet.
1:31 We don't have our database.
1:32 That's coming later.
1:34 But, we can get started this way.
1:36 So we're going to come here and say import
1:42 and let's say as just package_service.
1:44 I noticed there were some errors down here
1:46 so we can come and say .get_latest_packages.
1:48 Just like that, I think that's the only place it's used.
1:51 Okay, let's just make sure real quick
1:53 that we didn't break it. We did not, okay super.
1:59 That's what I expected.
2:00 So, that organizes it a little bit
2:02 gets some of the data access out of here.
2:04 But this, this is the ultimate problem right there.
2:08 However, it's tricky to reorganize it as is.
2:11 So this needs to be created
2:13 and then it needs to be used
2:15 to start the app in this main app.py.
2:18 And yet, it has to be available at the time
2:20 that these are parsed so that we can apply the route.
2:24 So, that can make it really tricky.
2:25 There are patterns that allow you
2:26 to share this across the file, different files
2:29 but because Flask has this built in thing
2:31 called Blueprints which are ways to predefine
2:35 these routes and then later apply them
2:37 after the app is created, we're going to use that.
2:40 It's really nice.
2:41 So, let's go down here and create a folder called views.
2:45 And in the views folder, we're going to create
2:47 let's start with two things
2:49 we'll have a file called home_views
2:53 keep adding that to get up.
2:54 And we'll create another one
2:57 called package_views.
2:59 We don't really directly work with these often
3:02 so the name isn't super important.
3:04 Okay, so what we need to do is we want to take
3:07 this is going to be the home stuff
3:09 and we're going to put it over here.
3:12 Well, immediately you can see the problem.
3:14 Some of it's just an import problem, that's easy.
3:17 Let's go up here and grab that
3:22 'cause of my renaming.
3:23 Okay that was easy, but the one that's left here
3:26 hmm not so much.
3:27 So, we're going to use this thing called
3:28 a Flask Blueprint.
3:30 And the way it works is we're going to come over here
3:31 and we're going to say Blueprint
3:34 you can also call it app if you want
3:35 but let's not confuse things here.
3:37 So we say Flask, which we have to import at the top
3:40 we say Blueprint and in here
3:42 we're going to give it three pieces of information.
3:45 A friendly name, so in this case
3:46 I'm going to call it home, 'cause it has to do
3:48 with the home_views.
3:50 And then for the import name
3:52 I'm going to give it the __name__
3:53 which is the name of this file, home_views.
3:57 And then we want to set the template folder to templates.
4:02 And then all we have to do is go down here
4:04 instead of doing @app.route
4:06 we say @blueprint.route.
4:10 So, we just replace app with blueprint
4:14 like so. Now, this sort of works
4:17 this will sort of add some features here.
4:21 And we go and run it
4:22 let's see what's going to happen.
4:23 We don't need this anymore.
4:25 So, let's see if we run it
4:26 is it going to be amazing?
4:28 The chances are it's not going to be amazing.
4:31 That didn't work.
4:32 But remember, potentially these
4:35 these are created before the app is there.
4:38 And how does the app instance know about it?
4:40 Well, we can do, there's a couple of things we can do.
4:43 But, let's define, let's do a little bit of work here.
4:46 Let's define a main
4:50 and move that up.
4:51 Now, before we do this let's call another function
4:53 called register_blueprints
4:55 or whatever we want to call it.
5:00 Like so and then all we got to do is say
5:04 so import home_views
5:07 and then we can go over to the app
5:09 this is the one that now exists here
5:11 and we can say register_blueprint, like so
5:15 and pass it in home_views.
5:17 And that's it, that basically goes back
5:19 and tells the app about the few routes
5:21 and methods and what not are defined over here.
5:25 It should work, let's give it a try.
5:27 And it did not like that. Oh
5:32 we can't aim for home_views, we have to
5:35 aim for, register home_views not blueprint.
5:38 Let's try that again. All right, there we go.
5:41 So, looks like it's running
5:44 but does it work? Moment of truth.
5:47 Of course it works. Of course it works.
5:49 Isn't that nice?
5:50 So that lets us break our code apart.
5:52 Our view code into these more specialized pieces.
5:57 So, it might not be convincing to you yet
5:59 how amazing this is, so let's go and add
6:02 another one here for the package.
6:06 So, for packages we're going to have a couple of things
6:08 and I'm just going to copy a few bits here to start out.
6:12 So, we're going to have a blueprint
6:13 and it's going to be packages, that all looks good.
6:16 And this is going to be packages
6:20 what we want to have is maybe a details.
6:23 And we're not going to do anything super interesting yet
6:27 let's just return package details for some package.
6:34 And here do we get to define our first
6:37 interesting route, I guess I would say.
6:39 This is going to be, let's remind us
6:41 what that's going to look like.
6:42 pypi.org, the real thing
6:45 click on this one, it's going to be
6:48 /project/<package_name>, okay.
6:52 So that's what we want there
6:54 so here we say package, let's do package_name.
6:58 Like so. Now, notice start away that PyCharm is saying
7:03 whoa, whoa, whoa there's something wrong
7:05 with this part of your route. What is wrong?
7:08 A function index does not have a parameter to take it.
7:11 That's so cool. So, we just go in here and say
7:13 it takes a string, now it's happy
7:15 and we can actually put that there as well.
7:19 Okay. Let's omit that out for a moment.
7:23 So, we should be able to run this.
7:25 Let's change the name, let's call this
7:30 And the blueprint, we're also going to have to
7:32 register this blueprint for it to work.
7:34 So, last thing, I need to go down here
7:38 to import package_views
7:43 like so and then we can import it
7:44 make sure everything's nice and cleaned up.
7:46 Did it rerun? Probably it did rerun.
7:49 Make sure, there we go.
7:51 So, we've got our two things here
7:53 but if we go to /project/abc
7:56 boom, package details for abc.
7:59 Okay, so we've defined our first interesting route
8:02 but maybe even more importantly for the moment is
8:05 we found a way to take our single super
8:09 mega monolith file that was defining our application
8:13 imagine there's fifty of these methods
8:15 and breaking them apart by category.
8:18 So, here we have home, these are the things
8:19 to do with like home and about.
8:21 And we'll have package and we'll have some
8:22 other package things going on here as well.
8:25 Of course we'll use that again in just a minute.
8:28 And then in our templates folder
8:29 I told you I was organize these
8:31 with this in mind so here we have home
8:33 we're also going to have a new folder called packages
8:37 in which case we're going to put our details.html.
8:41 So, let's just rob this one and call it
8:44 details.html, of course, it doesn't
8:48 have all the details yet, but it's going to.
8:50 So, this organization here is directly tied
8:54 to this organization that we did with blueprints there
8:57 so, I think this is a great way to organize your code
9:01 nothing about Flask encourages you
9:02 or suggests that you should do these
9:04 types of things, it's just a recommendation from me
9:07 you don't have to but I think it's going to be
9:09 really, really great as your app grows.