Full Web Apps with FastAPI Transcripts
Chapter: async databases with SQLAlchemy
Lecture: Find user by id and email, async
0:00 Next up, let's rewrite these two, get_user_by_id and get_user_by_email
0:04 here. So I'll comment this one out,
0:06 and it's gonna be quite similar to what we just did,
0:09 which I copied. So we're gonna create this async session, then I'm gonna create
0:12 a query, but now the query,
0:14 this one's a little bit more like what you would expect.
0:18 I'm gonna say, gonna create a select of user where we filter, I wanna filter by user,
0:24 what are we doing, id, this time equals user_id.
0:26 Now previously what we did,
0:28 as you can see right below is we did first().
0:30 So we're not gonna do that here.
0:32 The, we can't do those types of queries directly on the select statement,
0:35 we do it on the results.
0:37 We gotta come in here and get our result,
0:40 and then we're gonna say scalar_one_or_none.
0:44 So give us the actual value,
0:47 which in this case is gonna be a user object,
0:48 the one that you got or return
0:51 None. Don't crash if there's no results,
0:53 like if they pass the wrong id or in the case below,
0:56 we're checking to see if it exists,
0:58 right? Or to say, give me this,
1:00 Is there a user by this email?
1:01 Yes or no? So we could also rewrite this one really quickly as well.
1:07 In this case, it's just email and email for our comparison here.
1:13 And that should do it. Maybe format it like this.
1:15 Make it look a little better.
1:17 All right, so this should do it.
1:19 But in order for us to write this code,
1:21 we have to make this async functions, right?
1:25 And then where they're called, we have to convert those things to async,
1:29 right? It propagates up the stack.
1:35 In this case, we got our AccountViewModel,
1:37 and it's gonna need one of these def load,
1:40 which is an async function.
1:42 Then here it says, warning,
1:43 you have not defined a user class in the globals object yet,
1:47 right at the startup. So we want to make sure we always do that.
1:49 It's going to be an Optional[User],
1:52 we don't know if there's one coming back or not.
1:54 Initially, there won't be one. Now,
1:55 PyCharm should be complaining to us here,
1:58 but it's not so if we go look,
2:00 this is an async function and where we're calling it,
2:04 what we get back, as you saw is a coroutine.
2:07 So we need to await this right there.
2:10 Right, then up the stack. Where are we using this?
2:13 Well, we're using that in our view for account in the index right here.
2:18 So we'll await vm.load(),
2:21 which means this has to be async.
2:24 Now we're all the way to the top of the stack.
2:25 Hand that off too FastAPI,
2:27 and it'll go. Let's just see if this will work real quick.
2:31 So let me first log in, There's a problem, not gonna work,
2:34 is it? It does work,
2:37 look at that. We haven't changed that function yet.
2:40 So over here, we got Sarah Jones2,
2:43 and we were able to log in.
2:45 This is our slash account, which is running that code right, ups moved around, running
2:52 that code right there. Perfect.
2:54 The other one that we were working on is this one right here.
2:58 So we need to see where we're calling this.
3:04 We're just calling it in this one place where we're doing this check.
3:07 And so this one is already async
3:09 luckily, because we had to do that for the form.
3:11 So we're just gonna need to make sure we're awaiting this.
3:14 So we wouldn't have been able to register because it would have said coroutine is
3:18 not none. So that means the email was taken,
3:20 not actually true. Let's run this again and make sure we can register
3:24 now. I log out, register and register a third Sarah Jones.
3:35 See if she can register. First
3:36 let's try to register with her old self.
3:41 Nope, that email is taken.
3:42 Oh, yeah, that's right.
3:43 This is actually my email. Let's try that.
3:47 Boom. Sarah Jones3 was able to register.
3:49 All right, So hopefully you're seeing the pattern here,
3:52 right? What we do is deep,
3:54 deep down in the service layers,
3:56 we switched to the async session objects,
3:59 we await the database queries, that converts these methods to be async that just propagates
4:06 up the chain. So If we're over here,
4:07 in the view model, we have to make sure that the load, we have some
4:12 function that we can make async where we're doing these calls.
4:14 For example, this one already was. We had to make sure we added the await
4:19 right there to actually get the email back, not just the coroutine