Model And Schema Relationships (One To Many SQLModel) - FastAPI Beyond CRUD (Part 14)

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
what's up everyone welcome back now that we've been able to set up our authentication and also set up authorization for the different end points we're going to be establishing relationships across the different entities that are within our application for now we only have users and books but we can pretty much add any other database tables and other different modules so we going to be looking at how we can do that in this video we're also going be looking at how we can use our pantic to serialize data in these relationships and how we can return them on our API endpoints so to begin we have our users table which basically has all its attributes just like you see right here we also have the books table which has its attributes just like you see right here but want to achieve an application where users will be able to submit books and those books that are submitted by them will be tracked back to them so that means that there's going to be a relationship between users and the books they submit to our application so if we go to the next diagram right here we can see that we are going to establish a relationship between our users table and our books table and simply what you're going to do to establish a fing key on our books and that is going to be related to our user uid so once we've been able to do that then we shall go ahead and also look at how we can modify our structure of our AP end points or our responses so that we can return data containing these various relationships so the first thing we're going to do is to add a relationship between our books and our users and the way we're going to achieve that is by adding a forign key that is going to be relating our books table to our users table to do that we're going to Simply Define the for key as our user U ID now this user U ID is going to be an optional field because it's going to be aable build anyway so you have to import that optional class from typing so I'll just come right here at the top and say from typing shall import the optional class once that is imported we shall now come and say that this is going to be an optional but it's going to be the type of The UU ID so we're going to say U ID do uuid once that is done then we're going to Define what this field is going to be so we shall just use our field function and inside here we shall simply provide the default for this field which is going to be none and then we can also go ahead and to this we can point to that table or the column that we want to make the forign key so this is going to be a foreign key but it's going to reference the uid of our users table so for us to do that we shall have to look at our user model which created in our o directory this has the table name being user so that's what we have to use and then the field name that we want to set as our primary key is going to be the uuid so this is going to be a foreign key that's going to be referencing so for us to name it the foreign key we have to use the foreign key attribute or argument and in this case we have to provide the name of the table which is us as dot the field that we want to point to or reference which is going to be our uid so once this is done we're now going to go ahead and make this reflect in our database using almic so we set up alic in the previous videos and if you haven't checked them out please go ahead and look at how we set up our limic so to begin what I'm going to do is to create a revision for this migration I'll close some of the stuff I have here and open up a fresh terminal inside here I'm going to create the revision which is simply going to be a change or a tracking of the change that we've done so in our case shall just come and sayic revision and we shall autogenerate this so after autogenerating it we're now going to go ahead and create a message to Mark it as a revision so this message is going to be uh let's just say relate users to books and once this is done our migration our revision is going to be created now if I go go within our versions directory and look at this revision we shall see that a new column has been added to the books table just like you see right here and that is going to be aable field just like you see right here now we also see that a foreign key has been created and that foreign key is going to be having none so it's it's going to be created on our books table and it's going to relate the users table using the user uid but this is going to also refres the uid field on our user table so that has been our revision once that is done now the next thing we can do is to Simply go ahead and how and look at how we can relate a user to the book they've submitted every time they create a book now we shall go within our user routes or our book routes because that's where went ahead and created books and inside there we shall visit the endpoint that's necessary for creating a book now one thing you can notice is that in the previous videos we call these user details which is kind of misleading because what is returned out of this dependency is going to be the token details so what I'm going to do is to Simply go ahead and rename all these so that they can have token details instead of user details because that's what they return another thing I will do is to also be specific about the type of the user details I'm going to highlight every occurrence of this by pressing control shift and L and then I'll begin modifying them so instead of user details we are going to have token details and also we shall provide the type which is going to be our dictionary so we expect that this is going to return a dictionary and that dictionary is going to have our token details now once we've got our token details the next thing is going to be for us to get the user U ID out of those token details now remember when we creating the utilities to create tokens we basically went ahead and provided our user data but when you see where I create the token pair that's within our routes for authentication went ahead and provided our user uid inside our user data so for us to go ahead and access our user uid what you're going to do is to say our user U ID is going to be got from in our case our token details and since this is a dictionary you can use theget method and this getet method is going to allow us access the key which in our case is going to be the user but this is also going to be a dictionary containing the user uid so we're going to access that as well once that is done then let's go ahead and modify this create book service method that can allow us to create a book I'm not going to do to simply make sure that it creates a book but also assigns the user ID as the user U ID or the currently logged in user who has made that request so we're going to go back to create book and we're going to modify it by simply providing the user U ID and using that U ID parameter to go ahead and simply fill that new column which is our user uid so I'll just come right in here and while I create our book after providing our book data we shall also provide our user uid and this is going to be a string and once we provided our user U ID we are going to also go ahead and modify our book object so that instead of having none we can have a user uid so we shall say new book. user uid and for our case it's going to be user uid so this is just enough for us to use this method to create a book with the user ID provided so shall go back to our RS and what you're going to do is to Simply come right in here so after providing our book data shall now make use of this newly got user U ID so I'll just come right here and say that this is going to be our user ID so our user ID or our user U ID is going to have the value this user uid so I'll go ahead and format that so once I've been able to achieve that then let's go ahead and try to create a new book using the currently logged in user so I head over back to R Fox and I'm going to go to where I will create a new book now if I try to just simply use the Json that I have right here to create a new book we now see that we have an error if I go back to our terminal right here our server is saying that so our Ser right here is saying that the column user U ID user U ID of relation of relation book does not exist so let's go ahead and see why this is not working um did we I think we did not run the migration so we have to go ahead and apply this so for us to apply this we have to run almic upgrade sorry I forgot to run this so when run olymic upgrade head then will go ahead and make those changes reflect in our database and when we do that if we go back to our rest forx right here and try to create the new book shall see that it has been created so if you try to retrieve the user ID or try to get this book so let me try to do that inside Apple so of late found out this tool that can allow us to check for our connection to post as well as to navigate the data you R SQL statements and that is called SQL electron so I'm going to go ahead and open it up once I've opened it up it just has this simple minimalistic user interface and I can just simply connect to our database and right here we see our database that we created for our books so to access our tables we going to go to tables and then inside tables we shall go to public and inside public we shall see public. users public do books but what we interested in is public books if I open that then you shall see a newly created book which is this one but in this case it has our user uid added to it you also see that for the existing data that did not have a user uid now has been set to the default value of those fields so let's go ahead and try to make sure that we get the currently logged in users books so to do that we can just simply go to our book endpoints and create a new API endpoint for getting all books by our user so I'm going to get rid of this undefined Squigly line by removing this print statement and then this is going to be similar to what we have here except that we shall be able to provide the user uid so I'm going to go ahead and copy this I'll paste it right here and then instead of being on the slash boox root endpoint in our case we shall have slash books slash user and then we shall provide the user U ID so I'll say slash user ID once we have that then I'll go ahead and also modify the name of our get all books path Handler instead of being get all books in this case we shall say get user book submissions to be more specific and so this is going to be submission so get the books that a certain user has submitted within our application and then this is also going to require us to have the user uid so if I go right here I can simply go ahead and say that our user uid is going to be a string and once we've done that then we simply going to come down here so once we have that token details we can also get the user ID from there but want to make it Dynamic so that you can provide the uid of a user you can provide the uid of the currently logged in user and still be able to get the books for that currently logged in user so instead of using this so instead of using this book service gets all books method we're now going to make use of get user books method or if that's what we've called it so we have to go ahead and actually Define it so I'll say get user books and this will take in the session but it also take in the user U ID just like you see right here so keep in mind that this doesn't exist so we have to go ahead and Define it after I've defined this I'll have to go back to our service where we basically went ahead and got all our user or got all books from our database we shall create a new method that's going to be responsible for getting books by a user now this is going to be very simp to the one that we have here but it's going to contain some filtering so I'm going to go ahead and just copy what we had as get all books and then instead of get all books I rename it to what we called it so this is going to be get user books what I called it here so I'll say I'll copy this and then I'll simply provide it as the name of this method so instead of get all books you shall see get user books thing we're going to provide is going to be the user U ID so I have to provide it as well I'll say that it's will taking our user uid which is going to be a string and then the session object just like you see right here so we now see that this select statement is only getting all books and then ordering them by the descending book created so going to add a filter so I'll say where and for our case uh this is going to be ordered by the desending created at dat but we're going to filter by the book user U so shall say book. user uid is equal to the user uid provided so this will go ahead and F all books but it will filter using the provided user U ID just like you see right here so I'm going to go ahead and format that and save then head over back to our routes right here so we can now handle getting all books by a certain user we can also go ahead and get books for the current logged in user B simply using the token details user ID and then we can simply go ahead and do that but we're going to look at how we can do it in a more interesting way using relationship attributes so I'm going to go ahead and save and to test this endpoint what you're going to this to get to our forx right here shall create a new request so this is going to be get books for user and in this case shall create so I'll add a new or I'll just simply provide the URL right here it's going to be very similar to the one for getting all books and let me try to close what I have or some of the open API end points or requests so I'll just simply come and say get books for user I provide the URL but in this case it's going to be SL user and then slash the user ID so we have to get that assuming our currently logged in user is this so I want to get all books that were added by this currently logged in user I'll copy their ID and then I'll provide it in our URL so when I send we see that we are not authenticated and therefore I have to get the token I'll simply come right here and copy this token that we have I'll go in our headers I'll add our authorization header and then it file is going to be par and then token when I send we now see that we can retrieve the books that belong to a certain user so we are now currently using basic relationships and we're going to be looking at relationship attributes which which basically allows us to use a more object oriented way to achieve the same thing without having to directly use the ID now that we've been able to set up this relationship between our books and our users let us go ahead and look at how relationship attributes can make it easy for us to access them using reverse relationships so you're wondering what a reverse relationship is it's simply a way that we can access the user who created a certain book as well as the we can access the books that belong to a certain new in our case so to begin we are going to create create an attribute or a field on this book class and that's going to be the user field so this user field is going to be an optional field all this is going to allow us to do is to access the user whose user ID we have stored in here but we're going to access that via the relationship so in our case we're going to get access to this user model shall come at toate here and say from so in that case from from our o dot in this case we shall import our model so to do that shall just come and say source. o we are going to go ahead and import our models and once we've gone ahead and done that then we're simply going to provide our models do user and what this will do is to define the field that's going to Simply allow us to access the user who added this book or who submitted this book so we're going to be making use of the relation ship function which is one to just help us use relationships to get those objects that are related to a certain object such as the book object right here so we shall go ahead and import that shall say from SQL model shall import our relationship function and then we can say that our relationship in this case is going to be to the to the user table but we need to specify how how we shall simply return all books that are related to this user so in this case this user right here is going to have back populates which is going to be books so that means that on our user side we shall access all books that are related to this user and on our book side we shall just have to access the user who added that book but we shall access him via book. user so from the user side we going to have something like user dobox and that is what back plates is all about so when you go to our user model we're going to have something similar to this I'll go to our models in our o folder and then instead of having users we are simply going to have this being our books and then we shall do the opposite so instead of saying books this is going to be user just like we defined in our book class then let us go ahead and import this to so I'll go at the top here and say from in this case it's going to be typing we going to go ahead and access the optional field or this is actually going to be the list because we expect that we're going to get a list of books from the user object so I'll just come and import list and once we are able to do that then shall also import the relationship function just like that then I'll have to change this from an optional user object to a list of books that are related to this user so in this case we are going to also change this from model. user to model. book and then we shall have to import the models module so I'll come at the top right here and say from in this case Source do books we are going to import our models once this is done another thing we're going to do is to basically describe how SQL model or SQL alchem is going to load this list of books now SQL model by default uses lazy loading but it can be problematic in some ways most especially when you're dealing with an asyn DB API so what you're going to do is to come right here and use another way of loading so I'll just come right here and say SQL Alchemy or in this case relationship keyw arguments then we shall specify that we're going to Let's load this but we are going to provide uh select in now leave a link to this documentation that's going to allow you understand this in case I've not explained it well but what this is going to do is to Simply allow us to access the books that a user will have submitted and this is just the relationship attribute so once you've been able to Define this then let's go ahead and make use of this relationship attribute so just like we've been able to describe it here we're now going to go on our schemas of our user and then add that list of books so we have our user model and this is going to return that but in case you want to modify this so that it returns our list of our list of books with a user model we can simply Define that here on our schema by saying books and then we can use the typing list class can just come right here and say from typing we are going to go ahead and import the list class and once we've been able to do that shall just come and say list and this will be a list of books so we're going to import that uh at the top right here we shall just come and import the model that we want to go ahead and use to display books so I can come and say from source. books we can go ahead and import our book so I can get the book this is actually going to be from ask so when we say from source. books. schemers we can import our book so you have the book create model let us make use of the book create model so that we get less Fields now once I've been able to do that I can simply go ahead and provide this as a book create model and once we've done that then let us make use of this within our route for retrieving the currently logged in user so we shall go to our routes and those are going to be our o routes and within our o routes we have the path or the input for returning the current logged in user what it does is to Simply use our token get the user and then simply return that to user so once we've been able to do that we can simply go ahead and provide the response model and this response model is going to be the schema that we defined in here all the pantic model for the user model so I can just say that we shall make use of our user model to return that specific user with their related books so I'll go within our routes or within our rest Fox to test that I'll go within our rest Fox and when you try to get the current user in this case we are going to get an error so let's see where this error is coming from so we see that our books publish date is going to be a string but that is going to be a DAT time I think we shouldn't use that book model imported but rather let's just use the book model so I'm going to go ahead and import that book model instead of the book create model cuz I just needed list Fields so I guess when use book and then come and substitute this with book in our case if we go back to rest forx we shall see that the currently logged in user is returned with the books that are related to them so that's just how we can handle basic relationships and allow our API endpoints to return data that is related in this video we've looked at how we can set up relationships between related entities within our application we've also looked at how we can use SQL models relationship attributes to allow us return this data and we've also looked at how we can serialize it to be returned when retrieving it from our API parts if youve enjoyed this video please leave a like doesn't really cost anything and it's the best way you can actually help me to create more content thank you guys for watching and I'll see you in the next video bye
Info
Channel: Ssali Jonathan
Views: 315
Rating: undefined out of 5
Keywords: fastapi, fastapi tutorial, fastapi sqlmodel, apidevelopment, python
Id: H-7NNblkzrg
Channel Id: undefined
Length: 26min 48sec (1608 seconds)
Published: Wed Jun 26 2024
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.