Modern APIs with FastAPI and Python Transcripts
Chapter: Building a realistic API
Lecture: Partitioning with routers

Login or purchase this course to watch this video and the rest of the course contents.
0:00 Well, we're off to a good start. We've got our Jinja templates. We've got our static files. We've got our homepage. We're gonna add,
0:07 of course, a few more things. But before we get too involved, I want to add a little more structure,
0:12 a little more organization, to what we're building here. Now, to be fair, this API, this app, is not really complicated enough to
0:19 super justify this, but I would do it anyway and certainly as your API and your apps grow, you would really,
0:25 really appreciate some organization. So let's go ahead and put a few more pieces in here. We're gonna do "api.get".
0:33 Now remember I showed you that If we ask for a favicon it got a 404? I don't think we need request here. And all we gotta do is just do a redirect.
0:44 So we're gonna return FastAPI. Whoops, this should be "favicon ico" somebody ask for that. We're gonna do "responses, redirect response".
0:54 And where is it we want them to go? The URL is going to be "static/ img/favicon.ico" OK, so these are kind of related with the homepage, have to
1:05 do with that. And then we're gonna have an API, let's just put weather for now, and then we're gonna have this,
1:11 let's call it "weather" and let's just say it's gonna return some report for the moment. It doesn't really matter what we're returning.
1:17 But as you can see, these are gonna get more complicated, especially this one. We're gonna have more API methods,
1:23 and it's gonna just turn this sort of app startup file into a complete mess. So what do we do?
1:29 Well, no problem. There's plenty of organization that we can do. So let's go over and make a directory called "api"
1:35 and let's make one called "views". All the API implementations are gonna go in the API
1:40 one and the stuff that does templates basically is going to go in the views. Over here, let's make a file called "home".
1:47 Maybe we have stuff in like account management, one for I don't know, browsing weather locations and so on. But we're gonna have stuff to do with home
1:55 go over here. We can just go and nab these things and drop them there. It's not gonna work yet, but it's sort of the path.
2:02 And then over here, I'll add weather API. Go back, we're gonna take this one. Gonna put those there. Now, what happens if I run this?
2:13 Well, Surprise, it survived. Okay, That's cool. How about now? Does it work well? No. 404. What happened?
2:19 Well, the problem is how does this app know about those other things, right? We didn't import them.
2:27 We haven't done anything. So maybe we could do this "from api import weather_api and from a views import home". Maybe that'll make it better. Yeah,
2:37 that's not better. That's definitely not better. So we end up with this chicken and egg problem.
2:42 We need to create one of these here and then over here, we need to use it. But in order to find the weather stuff we've gotta
2:49 import it here, the way we would get it over there is we would import main. We'd import weather, import main, import weather,
2:54 that's a circular reference. Some languages deal with that, Python doesn't. So that's not how we want to organize these things.
3:01 So instead, we're going to use another concept called "API routers", put that back. So we'll go over here and say "import fastapi"
3:09 we'll say a "router = fastapi.APIRouter()" like that. What is the goal of this?
3:17 Well, whatever you would have done with the app or API itself, now we can do get, post, and so on. And then we add this router in to what we're
3:28 doing with the main app. So let's do that with the home is well while we're here. And we also have this template thing we had going on here,
3:42 which only actually makes sense in this place. So let's go and add that as well.
3:48 I'm gonna need to import requests from starlette, a little bit of organization, but no more errors there. No more errors here.
3:56 So the last thing we need to do, notice this where we're mounting the routes, I'm gonna improve this as well, but we need the "api.include_router()"
4:04 Let's do "home.router" and weather, "weather_api.router" Just run it to see that that works.
4:12 Okay, So what we do is we basically define little sub parts of our application in these routers, and we just bring them all together here. Run again.
4:20 Wooo! Beautiful, beautiful! If we click this, what's going to happen? We get some report. Awesome. So our API is working as well as our home page. And,
4:32 get it to refresh, Oh yeah, Check it out. We even got it to put the favicon up there. Super sweet. So we can use this.
4:40 We can use these routers to have a much, much, much better organization of our code instead of cramming it all into the
4:50 Final thing, let's do a little bit more organization here. Let's go and define a method called "configure"
4:59 and here we're going to, I guess we'll have configure, configure routing, and let's have a
5:08 function here. Why? Why would I have just one function that just calls another? Because we're gonna be doing other things.
5:13 Configuring the database, configuring API keys, configuring this, so this this area will grow. And now if I just run it like this,
5:22 we're gonna be back to our 404. Alright, 404. So what we need to do is we need to make sure that we call configure first and this is super tricky
5:32 what's going on here. A lot of times when we run in production, this code is not run in this way. So this should fix it, get it to come up.
5:41 There we go. So it works again. But let's see if I could make it run the way it would in production. Come down here. We would say "uvicorn",
5:50 I think it's dash, "-b main:api" like this. There we go. uvicorn. Let's see what we're supposed to do. Maybe it's just like this. There we go.
6:06 Alright, It looks like it worked yeah? So should be fine. we're back to not found again. What's going on? Here's what's going on.
6:14 Check this out. So it just imported this file, didn't run the main stuff, and that meant configure didn't get called. So we need to have an "else",
6:21 and this is what happens in production is down here. I'm gonna do this little configure thing.
6:26 Now I go down to the terminal and I uvicorn it. It's back to working, okay. And again, if I run it like this, also working. Awesome.
6:39 So we've got some organization done here. We've got the structure of our to help organize the startup code and
6:47 like things like database connections, all that kind of stuff that we're gonna have to sort of pile on here, right? Not quite there yet,
6:53 but we're getting there. And then, more importantly, we've put all the home stuff over here into the views.
7:00 And we put the API pieces into their own files as well. This one thing that we could also do is we could do
7:07 like this. Come over and say there's going to be all the views that have to do with home go in there. And we have a shared, that could go in there,
7:19 because as we have more views, you probably wanna have some structure as well. And that means, oh look at that. PyCharm
7:24 re-factored it. That is fantastic. Did it do it over here? No, no, no, no, man, if it did, that would have been awesome.
7:30 Say home slash to include the directory. Let's see how this works. Yeah,
7:35 it does. Layout is there. You can see you know that the layout got imported because of the CSS is still here.
7:41 Yeah. Perfect. Okay, so now we've got some organization around our templates, around our API's, around our views, and our main app, our,
7:51 our main app start up.

Talk Python's Mastodon Michael Kennedy's Mastodon