Modern APIs with FastAPI and Python Transcripts
Chapter: Accepting inbound data
Lecture: Weather report data layer
0:00 Let's begin our work on this writable data, this ability to accept data from users by creating the data access layer, not the API layer,
0:09 but the part that the API layer will use to read and write data. So fire up a PyCharm. Now I've gone and already copied what we did in the
0:16 previous chapter, chapter six error handling, over into chapter seven, moment, for inbound data. So it's just picking up exactly where we left off,
0:25 and we're gonna work over here by adding some other functions, not "give us the weather" but "here's a report" and "what are the reports out
0:33 there currently"? So in our services we've already got one service here for interacting with the
0:39 external API. I'm gonna add another one for interacting with the data around reports. Call it "report_service". This is not Web service
0:49 in that sense, this is just, like provides a service to the app, okay? Over here, we're gonna have two functions: def
0:56 get reports, and this one takes no arguments. It's just going to give us all the reports or maybe the last 10 recent ones
1:02 or something like that, and it's going to return a list of something. What goes there? I'm gonna have to create a class or something that goes there.
1:11 But for now, let's just return nothing. And then let's also defined on add report. This is gonna take a description,
1:20 it's a string. Remember, we already have over in our models, we have a location. We're gonna let, you know we need to have a location
1:27 for that particular report, right? It was in Portland, or it was in New York City or whatever. So we're gonna pass that over,
1:35 which means we gotta import that, and then it's gonna return something,
1:39 Something up here. We're gonna say it returns something for the minute like this.
1:43 But what we need to do is we're gonna define the class. The same thing we return there is the same thing that's going to be contained in these lists.
1:50 Now we're going to need a database to store this in. Just like I said about the caching, we could set up interesting infrastructure.
1:56 We could use mongoDB, or we could use postgres, or we could use some other system to store this, or who knows a file system,
2:02 Some random thing. But because I want to keep this super, super simple for you, I'm just gonna have a empty list here. Now, we can just do return
2:12 a list of the reports. Why not just return the reports itself? We don't want them to modify it, so we're going to return a copy of it.
2:20 I guess we could just do reports.copy but this will have the same effect. But here's the thing, If we go to one of these and we say "dot"
2:27 what's in there? We don't know. So it's gonna be good for us to define a class that holds that.
2:33 And it makes sense for us to define this at different levels because it's gonna be easy for us to reuse some of it over here. Now,
2:40 in practice, I'm not sure that would really happen. In practice, we might have database models and then pydantic models on the edges.
2:46 But for this case, let's just go over here and create a file called "reports". And what we'll do is we'll have a class called a "report".
2:57 We'll start out in one way that's not where we're gonna end up, but we'll have a base model. And what is the report gonna have?
3:03 It's gonna have a description, which is a string, and it's gonna have a location.
3:08 Now, this is super cool what we could do with pydantic here. Location, which is a location of that variety.
3:16 So what we can do is we can say our report actually has this description and a location and we also wanna have a created date, which is
3:24 an optional datetime. I've got to import a few things to make all that work. Dot datetime. So this was "when was it created"?
3:34 Perfect. This is the object that we're going to exchange. We're able to use our location already. We're here in the report services.
3:41 What this is going to do is going to return a list of report. This, we still don't know what goes on here, right? We still don't get any help.
3:49 But if we go up and say "this is a list of report as well" all of a sudden PyCharm and
3:55 everything else knows it has a location and locations have countries and so on, right? So this is really a good idea.
4:01 Put the type there, and then this is now going to return a report. So when we go and pass this data over,
4:08 it's going to create this object and then send it back as well as store it into our reports list. So let's go over here and just capture what
4:16 datetime dot now is, like that. And we gotta import that here as Well. Then we're gonna create a report, which is a report of this type.
4:28 And notice, it takes stuff here, some arbitrary data, and the data it takes is "location equals location,
4:37 description equals description, and created date equals now". And then we're gonna return the report, but we also wanna save it.
4:47 Now, this is where we're simulating saving it the database because we're just having this simple thing like that.
4:56 Alright, so we're gonna create one of these, put it into the report, saving location, the database type of thing, and then we'll just return it there.
5:05 Alright, let's see if we can actually do a little test on this. Not terminal but the console. So let's see if we can make this happen.
5:12 So from services import report service, then we can try report service dot get reports, should be an empty list. We're going to add a report.
5:25 What goes in here? We have the tornado and the location. We're gonna have to import that. Hold on. Alright, let's see what happens if I run this.
5:42 Oh, that's pretty cool. Alright. And then we have, this is our item here. We've got our created date and everything else,
5:49 so it looks like this is great. Let's add one more report. This one is gonna be in Beaverton, a city near Portland. This is going to be hail.
5:59 Now if we get the reports, we should have, it wraps wraps, wraps, wraps, right. We've got our hail and we've got our description there.
6:09 Another thing that we probably want to do. When we put these in and then we ask for them back, we probably want to get the most recent ones,
6:16 not the oldest ones. Right now, we're getting them in the order they were created. We probably want the most recent. So let's do, after we do this,
6:24 let's do a sort here. We'll say given some kind of report, what we want to do? We want to sort by created date, reversed
6:35 true. And now I guess if we, we could re-import this and do the same
6:41 things, but you'll see that it's been reversible. It's getting a little clumsy to play with. So we've created this data access layer,
6:47 talking to our fake database. One final thing I want to do is I wanna make this feel a little bit
6:52 more real, even though I am faking it with this in-memory database. So in a real database,
6:59 we would very likely wanna have an asynchronous database driver or library to talk to it
7:04 like the new version of SQLAlchemy or peewee or some of these different ones. We'll make this async, and I'll just put a
7:13 message that says this would be an async call here. It's not. We're not actually using the async aspect. But like this part right there,
7:24 right, this would be the data call, right? This would be insert into the database and this would be query from the
7:29 database. So just to give you a more real feel when we consume this in our FastAPI, this is probably what you want to aim for.
7:37 So we built our models and we built our little data access layer. we should be able to create an API around this real easy now.