MongoDB with Async Python Transcripts
Chapter: Beanie Quickstart
Lecture: Beanie Quickstart: Part 1 Classes

Login or purchase this course to watch this video and the rest of the course contents.
0:00 New chapter, new folder. Let's create our application code. Now in this one, I wanna show the different stages and the different steps.
0:11 And so I think I'm gonna create four copies of the same bit of code, but evolving as we go. And to accomplish that, I'm gonna give it
0:20 a particular name of P1 as in part one, and then we'll have two, three, four, and a little description of like, well, what is the point of this?
0:30 So this is to explore how we model with classes, kind of like Pydantic, but not exactly. So in our quick start, we're just gonna model user accounts.
0:41 So users, when were they created? What is their location? Things like that. Now, in Pydantic, we saw what we did is we created a class
0:51 and we gave it a name and it derived from Pydantic.baseModel, right? That's pretty much what we do with Beanie as well,
1:00 but we're going to derive from a different base class, one that doesn't just say this is a data exchange class,
1:06 but it actually knows how to have, say, queries on it. And it knows how to, by default, bring in an underscore ID primary key that MongoDB requires.
1:17 All right, so we need something a little bit more focused that is itself a base class of Pydantic.BaseModel. So let's go and add Beanie here.
1:27 So in order to work with it, obviously we need to pip install it. Now I want to point out with this requirements.in, you don't have to do these steps.
1:35 I'm just doing them to generate the requirements.txt. All you'll need to do is pip install -r requirements.txt. So let's do our pip compile.
1:48 And it says, look, there's a bunch of other stuff, including motor right there, that we need. And we're going to pip install -r requirements.
2:00 And we also learn a little bit of stuff by doing that. You can see that motor itself uses PyMongo for a couple of things.
2:09 So we're going to have both, but we only program against motor. So let's change this to be Beanie. Hello, Beanie. Finally, here you are.
2:19 So what we're going to do is drive from Beanie.document. So what you know about Pydantic basically applies here as well,
2:27 because that is ultimately a Pydantic class too. For our user, well, we're going to want to have an underscore ID,
2:34 but that almost always in MongoDB is just one of these object IDs. And unless you need to change what type it is, we can just inherit that from here.
2:44 If for some reason we wanted this to be a string like an email, we could write this, but we don't have to.
2:50 Okay, so let's say we're going to have a name, and the name is gonna be a string, this is username. We're gonna have an email, which is a string.
2:58 And we're gonna have a password. And maybe the password is not set when we first create the document, but later it gets set through some kind
3:06 of authentication process, or you know, verify your email, then we'll create your account. And so in order to create this document,
3:13 just like we saw with Pydantic, this needs to be an optional, which comes from typing of string. Now, again, you could say string pipe or,
3:25 I'm not a big fan, it doesn't communicate to me the same thing as this is either a string or nothing. I know the word sounds similar,
3:33 but optional means like it's either a string or it's just not there. And so I prefer this, either way works. Now, do I wanna store the direct password?
3:41 No, no, never, never, no. So what I'm gonna make sure is we explicitly call this hashed password or password hash or something like that.
3:51 Let's call it password hash. So when you're doing auto-complete, you can say, you know, user.p and then boom there.
3:59 Oh, it's not the password, but the password hash. A little bit easier on us that way. So these are all standard values
4:06 that either have to be set or if they don't get set, they just don't get stored at all. There's other information though
4:14 that we might want to store about this user here. For example, something that I put in most of my top level database classes
4:22 is when was this thing created? I find like when I go back in time, it's always really helpful to know, oh, that was created a week and a half ago,
4:33 or it was created this time. It allows you to write queries and reports that say show me all the users created this week,
4:39 or how many users do we get per week, week over week as like a growth metric, okay? So a created date, and this is gonna be a date time,
4:50 which we got to import, date time dot like that. Maybe we also wanna know last login date and the time they last logged in.
5:01 This one, we probably have to manually set every time they log in somewhere, but when they first create their account,
5:07 we want that to be the same as the created date, as well as when this gets created, no matter who inserts it, what part of code does this,
5:16 We want this to get set. So we saw before that we could have default values here like Jane@doe.com. Remember we had Jane Doe for the name
5:27 in our previous example for Pydantic. So we can do that here as well, but with a lot more control.
5:35 So what we can say is this is gonna be a Pydantic.field. We're gonna set, you can see there's a default and a default factory.
5:46 The default value is a fixed thing that is always set. So for example, it might be a number, like default is zero or Jane Doe or something like that.
5:57 The default factory is a function that gets called every time this object gets created, but only the first time. When it comes out of the database,
6:06 it uses the database value, but when it's never set, like the very first time we try to insert it, the default factory will be run.
6:13 So with that in mind, what we wanna do is call the now function on dateTime. DateTime.dateTime.now. Now, be very careful here.
6:23 When I hit Enter, what is PyCharm? And most editors gonna do, it's like, Here's a function, you wanna call that, right?
6:29 Mm-hmm, no, no, no, no, we don't wanna call it. And PyCharm is showing us like, Hey, that should be a callable.
6:36 And no, it's not a callable, it's a dateTime value. So what we're passing is the now function, not the now result.
6:46 And we'll do the same thing here as well. Again, the very first time when we insert it, we're just gonna call now and give us that time,
6:54 but then later as we get the record back, you know, they log in some other time, we'll set this explicitly. But this will give us the created date
7:03 and the last login time set to basically be the same right when the user gets created. Now the last piece of data we wanna store with this user
7:11 is their location. So in a traditional database, you might say something like street address one, which is a string,
7:23 street address two, which is an optional string, right? 'Cause it might not be set, city, string, and so on. But in document databases,
7:34 we don't have to have everything in a flat layout. We can do something a lot nicer. We can come in here and say, So we want a class called Location.
7:44 And Location can have a-- let's just do a city, state, and country. You can imagine that, of course, all the other state things you've got to track.
7:59 And just like with Pydantic models, you can embed one of these into the other. So we can come down and have a location.
8:08 and its type is going to be location. Now, when it's set like this, we have to explicitly create one of these
8:16 and assign it just like you would with a string, or we could give it some kind of default value. Don't think that makes sense here.
8:23 What is the default for location? So we're just gonna have it like this. All right, so this is our user class.
8:30 Now, let's go and write a main method here that we can call. And in fact, let me put that right at the top so people can see what's going on.
8:41 And here, what we're gonna do is we're just gonna create a user equals a user like that. And let's go ahead and run,
8:51 this will say print creating new user. Print done. Spoiler alert, we're never making it done. All right, so down here, remember my alias,
9:04 I wrote my name, boom. There we go, name, dunder name equals dunder main. And let's just go ahead and run this and see what happens.
9:12 Well, a lot of bad things have happened. No validator for location. Okay, so the first thing that we did is said, okay, this is not going to work
9:24 because Beanie looked in here and said, or Pydantic, I'm not sure which layer looked at it and said, you know, we can't embed an arbitrary class.
9:32 So this has to be some kind of Pydantic-like class. It doesn't, it should not be a Beanie.document because it'll have an underscore ID.
9:42 It's not a top-level document, that doesn't make sense. So this is just a Pydantic.baseModel. Okay, run it again. There's more errors.
9:51 And it says, look, the name, email, and location are required. If we go right, not there, that was too quick. But the problem is right here.
10:02 Okay, it says you have to supply these values, these three values that are not either optional or don't have a default.
10:11 So what we need to do is go over here and explicitly set the values that are required. So we've got to set a name and an email and a location.
10:22 So name equals Michael, email. I create this location inline, but it's another object. Let's go ahead and create it separately here.
10:39 And what does it take? It takes city equals Portland, state equals Oregon, and country equals USA. All right.
10:53 Now that we're setting this, let's see if this code will run. Now there's one more thing we got to do in order to work with this object here, and that
11:03 is initialize the connection. So basic Pydantic models are perfectly content to have us just create the model in memory,
11:13 but Beanie documents ensure that they'll be able to do things like write queries or save itself to the database.
11:20 order for that to happen, you've got to already set up a database connection before you create one.
11:26 Okay. Just so you can see some output here, let's temporarily put this as a
11:32 pydantic dot base model. And I'll comment that out. Okay, all the validation passes. And let's just print print out the user to see what we got.
11:48 So you can see the stuff that we set, the name and the email, the password hash is none,
11:52 but because it's optional, that's fine. And check out the created date and the last login date.
11:58 Excellent. And the location itself is an embedded location, Portland, Oregon, USA.
12:06 Super cool. Super cool. Okay. For this, I told you there's multiple parts. For part one,
12:12 I'm going to leave it like this with the beanie.document commented out. But of course,
12:17 when we get to the next step, which is connecting to the database, we're going back to the Beanie model.


Talk Python's Mastodon Michael Kennedy's Mastodon