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