FastAPI and Pydantic - Model Classes and Nested Models

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
in this video we're going to introduce pantic and we're going to see how it's used with fast API and we're going to create some models based on the schemas that we already have in our sample application and we'll also see how we can work with nested models in a fast API application let's dive in we have the documentation open for pantic and we can see that it's the most widely used data validation library for python now if you're interested in learning more about pantic I did a YouTube series on this library in the past that should be appearing on the screen now but what pantic allows us to do in a nutshell is create classes that inherit from its base model and these classes contain fields that Define the structure of a piece of data that you're looking at so for example a delivery might have a Tim stamp and some dimensions and you can take each of these fields and you can add a data type to them using the python type hinting so this kind of package is very helpful when you're validating data that's coming into your API for example and a request body you can validate that data and you can then decide whether or not you want to actually add that data to your database just as an example and pantic has many use cases but fast API is arguably one of the most common so what we're going to do now is just dive into the video and I'm going to open up VSS code and we're going to start defining some models again if you're interested in more check out the series that I did before for now let's create a schemas dopy file and in this file we're going to create the schema and that's basically the pantic classes that we're going to use in this application to start with in main.py in the last video we created this enum class I'm actually going to cut that out and I'm going to paste it into schemas dopy as well as the UT itself at the top here so let's cut that out and paste that into the schemas dopy file so in the schemas file we're going to Define any kind of data that we have in the application as well as the model classes that Define the structure of that data and that's why for this video example I'm going to move the enum into this file F we don't want the main.py file becoming cluttered with all sorts of different types of code so it's a good practice to create modules for specific things in your application and what I like to do in fast API is create a schema. py file and add all of my pantic schemas to that file so with that said let's now import from pantic that base model class that we saw and the base model is what we're going to create a subass from and we're going to do that just below the enum here and the data that we're modeling is data for music bands so we're going to create the class called band and that's going to inherit from that base model and now we Define the fields that we want on that particular class now in order to get the fields what I'm going to do is go back to main.py we defined this list of dictionaries in the previous videos what we're going to do is copy one of those and I'm just going to add this as a comment just now where we Define this schema so the band model will have an ID and that's going to have a data type of integer bands will also have a name which is going to be a string and a genre and for now I'm just going to set that equal to a string as well we have above this class the enom here containing the genra URL choices but that's specific to the URL which we know will lowercase any kind of genre that we pass in so the values for this enum are in lower case whereas we have a genre here within the dictionary and the starting letters for those values are in uppercase so we're not going to use this directly because the actual values here would not map to what we have here in the dictionary now we'll see later on ways in which we can limit the genre field of the model to a predefined set of values but for now that's enough for this model we're going to remove the comment we have a very simple class here with an ID a name and a genre field what we now need to do is go back to our main.py file and we're going to import those two objects from our new schemas dopy file so from schemas let's import the genra URL choices and also the band model class and we're going to change this function here and this is the hand function for returning a list of all of the bands that we have in the database and I say database but actually I'm referring to this hard-coded list at the moment We'll add the database later in the series so what we're going to do is change the return type rather than a list of dictionaries we're going to change that to a list of these band objects and the logic for this function rather than returning that list of dictionaries we're going to convert each dictionary to the pantic model instance and we can do that by taking the band model and we're going to unpack all of the keys and the values for each band in that list of bands and we can do that with this statement here it's a list comprehension in Python and for each band in the list of bands in other words each one of these we're going to take each key in value and pass it in to the Constructor for this band pantic model now if we save this and go to the terminal what I'm going to do is run the uicorn server here we can do that with the command uicorn main colon app and as before I'm passing the reload flag here now that's that's going to start a server what I'm going to do is go to the browser and we're going to navigate to this/ bands endpoint and this is the response that we're getting it's exactly the same before we have all of the Bands listed out in this API response now why have we used pantic what's the benefit of using this model class instead of just using a dictionary well first of all we have data validation built in when you tell the Endo that we're returning a dictionary there's no validation whatsoever on that data but on the other hand when we tell it that we're returning a list of these model classes the endpoint is going to take each field in that model and it's going to apply the validation logic so for example if we passed a string as the ID it's going to reject that so we get that extra validation of the data that we're actually returning in this case from the API and another benefit of using the pantic model class in your endpoints is you get the documentation for that particular model so if we look at the endpoint / bands here what we have now as a successful example of the response is the correct schema down here that contains a list of these objects and the actual objects now we know the names of the fields that we're expecting to get back in the response so we know for example that we have an ID a name and a genre and we also get a sample value for each of those fields based on the data type that's used so by using the pantic model our documentation gets much more information about the types of responses in this case that we're sending back and it gives us better documentation to share with consumers of the API so let's now go back to VSS code and refactor the other endpoint so this one is to fetch a single Band by the ID that's passed in as a path parameter currently that is returning a dictionary but we're going to change that to return an instance of the band model and we should say that fast API obviously works very well with pantic and when we specify that a pantic model or a list of these models should be the return type fast API will take care of converting those model instances to Json data so this endpoint should now return a band what we need to do is just change a little bit of the logic here we're currently fetching the band based on looking up the ID here so instead of just returning the dictionary we can then again create the band object and unpack the keys and the values from that dictionary and if we save this and go back to our browser here I'm going to go to localhost 8000 slbs and let's add the id2 here and we get back the cor value and again let's go to the documentation if we look at bandsband ID what we had before all that the documentation knew here was that we were returning some kind of dictionary it didn't know anything about the keys and the values in that dictionary but if we refresh this page now that we've added the pantic model and we go back to that endpoint we can now see we get a sample schema so again much more information for the consumers of your apis and that includes maybe front-end developers that are integrating with that API those developers if they're building a react app or something they need to know the names and values of these fields and this allows them to build out the schemas on the front end and show that data ultimately in the user interface now so far we're just modeling and returning data that's being returned from our API but we can also use these pantic model classes to create a structure around the expected data that's sent in a post request in the request body and in those circumstances when your clients are sending data to you validating that data correctly becomes even more important so we'll see examples of that in the next couple of videos in this series now what I want to look at now is I want to look at nesting pantic models so let's go to schemas dop currently we have a band model but let's say we wanted to allow a band to have a list of zero or more albums and this is natural some bands have not yet released an album but some bands have been around for a long time and they might have 30 or 40 albums what we can do here is create a new new pantic model class and we're going to call that album and that's going to inherit from the base model and I'm just going to keep this simple and add two fields to the album model so an album has a title which is going to be a string and an album also has a release date and we're going to set that to a date object in Python and we need to import that at the top so at the top I'm going to say from date time let's import that date object now we could add additional fields to the album such as genre now we already have the genre in the band but some bands maybe think of radio head or something they change genres sometimes from album to album but we're going to keep this simple for now and just keep two fields on the album model now what we need to do in the band model because a band can have a list of albums is we're going to add a new field called albums and we're going to make that equal to a list of these album models and we're getting this yellow line and that's because I've defined the album model underneath the band so if we reverse the order of that we're going to remove that error so a band is going to have a list of albums but of course as I said some bands have not yet released an album so we're going to set a default value on this field and we're going to default that to an empty list so let's save the schemas dopy file and now that we've added a new field to the band model how is that going to affect our two end points that are returning the list of these models and also a single instance of the model let's go back to the browser and we're going to go to Local Host 8000 now this is the detail page that returns a single band if we now send this request again to the server we get the new key and value here so we have albums and that's returning that empty list and if we go back to the list page for all of the bands at the/ bands endpoint we see now that every single band in that list has that albums key and for all of them of course we have an empty list as the value and the reason that's an empty list is because in our model we've set that default value we could have set that to none for example example and if we go back and refresh the page that changes to null so the default value can be used as a placeholder for when the values are actually missing from the model and you want to set some kind of sensible default so let's change that back to a list and what we're going to do now is go back to main.py and I'm going to go back to this hardcoded list of bands and what I'm going to do is for the bands Black Sabbath I'm going to actually add a new key here called albums and we're going to set that equal to a single album in this case it's a list containing a single dictionary that represents the data for that album and that has two keys one for the title master of reality and the second key is for the release date and you can see that that was released according to Wikipedia at least on that specific date in 1971 so we've added an album and what's going to happen now if we go back to the endpoint if we refresh this page you can see that now for Black Sabbath we're actually getting that nested Json data so we have a key for the albums but unlike before there's is now actually an object within the resulting list and we're getting all of the benefits of pantic even in that nested model so all we need to do is Define that that nested model that child model and what we can do then in the parent model is add a reference to that model and any validations on that child model will be performed when we send that nested data for the band and just to show an example of that if we go back to main.py and we change one of these keys for example title let's change that to titles and go back to this endpoint and now we're going to get an internal server error and that's because we don't have a schema that conforms to what we specified here in the album class and another example of this data validation if we go back to main.py we're going to change the key back to the correct name which is title but the value we're expecting here is a string if we change that to a number for example let's just say the number two if we go back to the browser again when we refresh this page we're going to get that internal server error and on the term Al you can see the error that we're getting the input should be a valid string but it's currently not a string it's just a number two so let's change that back to master of reality back to a string and we're going to go back to the page and refresh this page we now get the list of all of the bands and this is also going to work with the detail page and you can see Black Sabbath has this ID so if we go back to the URL and we specify that ID we're getting the detail page for Black Sabbath that contains that album that we added and if we add another album just just as a demonstration here I'm going to copy this down it's the same name obviously you wouldn't do this in real life but if we go back here and refresh we get all of the albums associated with that band in the response so that's all for this video we've seen how to use pantic models within a fast API application and we've seen if we go back to main.py how to use those models as typ hints in The Returned content from our Handler functions later on we'll see how we can use pantic models to give proper validation to parameters that are coming into our API Handler functions and in this video we also saw how we can use nested models in a pantic schema and also how we use the model classes and how they augment the API documentation with information about the schema that's going to be coming back from the response in the next video we're going to look at query parameters in fast API and we're going to see how we can use the enom class that we defined earlier in the last video to perform data validation on those query parameters so thanks again for watching this video if you've enjoyed it please like And subscribe to the channel and if you're enjoying this content please consider buying the channel a coffee there's a link in the description of the video and we'll see you in the next video
Info
Channel: BugBytes
Views: 2,531
Rating: undefined out of 5
Keywords:
Id: ID9b4diFZN8
Channel Id: undefined
Length: 14min 45sec (885 seconds)
Published: Mon Nov 27 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.