💻Pydantic Tutorial for Beginners: Enhance Your Data Validation Skills

Vaibhav Mera teaches Pydantic v2+ for validating Python data with type hints. Learn BaseModel classes, Field constraints, custom validators with @modelvalidator and @field_validator, and nested models. Built for APIs, FastAPI, and AI agents.
Chapters
Hi Data Scamps and Data Champs. Data validation is an important part of ensuring data quality and Pydantic is the standard tool for this. If you're suffering from bad data or you're tired of writing clunky custom validation code, then Pydantic is going to make your life easier. In this video, you'll learn how to master the basics of Pydantic, set your own validation rules and easily handle nested data. Follow along with the code link below and check out the recommended courses in the description below. That said, let's jump right in. Hey guys, what's up? My name is Vaibhav Mera and I'm an AI instructor here at datacamp. In this tutorial we'll be covering an increasingly popular library called Pydantic. Now, Pydantic, it's a powerful Python library that makes data validation and parsing super, super easy using type hints. Now, there's a whole range of applications which you can use Pydantic for. For example, you can build software with it, or you can build your AI agents with it, or anything Python related. The main thing is Pydantic will applications much more robust. So if that sounds good to you, I will see you at the code again. Welcome to the Pydantic tutorial. There are two prerequisites for this course. Number one, Python. You need to know quite not a lot, but you need to know the basics of Python. And number two is you need to know basic OOP knowledge. Now I assume you do know these two and that's why you're here. If you don't, then there are a whole host of resources here on Data GAM which you can use, such as the courses on our website. Apart from that, if you do know them, let's crack on. So what is Pydantic? Officially, Pydantic is a data validation and parsing library that enforces type hints at runtime using Python's built in type annotations. Now that probably didn't make much sense, but in simpler words, we can get these features, number one, we can get automatic checking. It checks that the data we receive matches the types and constraints we define in our model. Now, if in this case a model is not like an AI model, it's really a class and you'll see what I mean in just a second. Number two is conversion. It tries to convert data to the correct data type whenever possible. And number three, it uses structured data handling. So it lets us define complex nested data structures using these models. Again, not AI models, these are classes. This ensures that all of the data inside is validated and accessible in a structured way without having to write a lot of these, if else, conditional statements, which could be, well, quite cumbersome. When writing in Python, we often work with APIs, databases, forms, jsons, a whole host of external data. Now, this could mean it's quite messy and quite inconsistent or wrongly typed, and that is a huge problem because it can cause a lot of logical errors. And this is where PYTIK comes in. It makes sure that the data we're working with is correct, clean and well structured. Now, tldr, we can define the shape of our data once, and Pydantic ensures it stays that way. So that was the main introduction to what Pydantic is. Now let's actually start coding it. So to start with Pydantic, all you need to do is PIP install Pydantic. So I can run this and you can see that it is installed. And now I can import Pydantic. And this should run flawlessly because it's just a simple PIP install. So hopefully it does run flawlessly. Now, the key thing to note though, is that your Pydantic version, which you can check through this command, must be higher than 2.0. There's a Pydantic 1.0 version as well, but that is slightly different syntax changes. So I'll be using a Padanti version, which is higher than 2.0, in this case 2.1, 1.7. Now, let's crack on with Basic Models, the first section of this tutorial. So let's create our very first model. So to do that, we need to import this first line from Pydantic. Import base model. Now, base model is arguably the most important thing in Pydantic. This module basically enforces type hints at runtime. Now, to create a model, like I was saying before, we create a class, and this is where you need to know oop. So we can define a simple class, say for example, a user class, like this class user, and then we pass in base model. Now, in this case I've defined three fields or three parameters, Name, age and is active. And you can see that I've created type ins for all of them, the string, an integer and boolean. Now, there's a lot of type ins which you can do, but these three are the most common, so I've gone for them for this very first example. Now, just like normal oop, we can create an instance, and in this case I've called it user one is equal to Bob, who's 30, and he is active. He's actively a user for whatever company we're making it for. And now if I print user one and user one model dump, which you'll see in just a minute, you can see this, that the name is equal to Bob, 30 is active True, exactly what we had written here, and that the first statement was done by this print statement. The model dumb is in this format where you can see it's in a dictionary format. So we can see the actual name Bob age 30 and is active true. So there's different ways to print the same thing. My preference is using model dumb because, well, it's in a dictionary format and I just prefer it. But you can achieve the same print results using either of these commands. Okay, so now let's move to the second example. In this case, I've created a student. Again, it's very similar to the first example where we had created a user and the only thing which I've changed is the isactive from a boolean type to a string. So the name is string, age is integer. But you can see in this case I've created a default value. In this case, 18. Now, what are default values? Now, when you instantiate an object in this class, you might not necessarily want to pass an parameter. And this could be for several reasons. For example, if you're building APIs, that API might not have that parameter passed in. So to do that you can create default values. For example, you could have set this to none, but in this case I've set it to 18. Now, what does this mean? So if I remove this age and I run this, you can see that name is Jeff, age is 18, and subject is mat. Again, this is quite basic stuff, but we're building it slowly and you can see that the age has been 18. Why? Because this was the default value. But if I had written age is equal to 16, for example, and run this, you can see that it's overwritten the default value. And you can see that I've written this in the comments as well. By the way, you will be able to see all of this file and run all these examples from the GitHub down in the comment section below. Now let's move on to type validation. This is where we take it up a notch. And this is the first interesting thing which we're going to see. Pydantic has inbuilt conversion. So if you remember in the introduction part I had said Pydantic can convert it Means trying to convert data to the correct data type whenever possible. So we'll see a great example here. Again, we're going to use the user class or the user model which we had defined here. But look at this name is equal to Bob. Age is equal to 25. IsActive is equal to true. Do you see what the problem is here? The problem is that age equal to 25. We wanted age to be an integer, but we've passed it accidentally as a string. Now obviously this is quite easy to spot, but if you had a lot of parameters and a lot of different objects, this would be very hard to spawn. So pydantic comes in like quite well here because it automatically converts it into an integer. Because I just ran this and you can see the data type of user 2h is, well, an integer. So that's a great thing. It saved us there. But there is an invalid case though. For example, if I uncomment this and I run this, you can see that we've got a validation error. Why? The thing which I had created, the object is Charlie 20 and false in this case, 20 is not actually the number, it's the actual word of the number, right? And there is no way it can well convert that because it doesn't have intelligence like that. So in this case it was able to convert it because it was quite a simple conversion. Just essentially remove the quotation marks and convert it into an integer automatically. But in this case, even if it does remove it, it's still a string or a list of characters, right? So it can't. That's why it gives us a validation error and it gives us where the validation errors occurred and input should be a valid integer. Unable to pass string as an integer and you can see what's the value which the error is coming through. That was how to create basic models in Pydante. Let's move to the next section where we'd look at fields. Fields let us add metadata, AKA data about the data, validation rules and custom behavior to a model field. This will make more sense as we code it. But if you want some further information, you can go onto this documentation. The documentation is great. If you click this link, this will open up, you can see that it's about fields and there's a whole host of information about the different subsections and there's also all of these different stuff here as well. Now we'll be covering quite a lot of this anyway, but if you want to go deeper and understand all of the different things you can do for fields I highly recommend this documentation. It's really well written as well. Okay, now going back to the code, we'll create a very basic example. You can see in this case we've added another module to import, which is field. Now let's create a new, completely new model and we'll call it field user. I know it's not very original, but still. And you can see that in this case I've created one variable which is name and it's a string, and this is the field. In this case I've done written the description. So this is the user's full name. Now this could be especially useful, especially for things like AI agents, where the underlying LLM might want some metadata about what each variable is for. Obviously you could pass it as a docstring, but it also does help if you provide as much context as possible. Anyway, so this is one parameter which you can put in field. And if we run this, you can see it's a very simple example name veba, which is my name, and we can just print the field user and you get everything right. This was how you can use a field. Let's go for a slightly more complicated example. If we go here and again field user default. You can also set default values using field. And in this case default is John. And if I run this and I don't pass anything, obviously it would be John. But if I had passed in a name is equal to Sam, for example, the name which would have been printed would be sam. That's all good, but here we go. We have a problem. Pydantic does not validate the default value by default. Now what does that mean? For example, let's say I've created a model called floor user. Why? Because this user is floating. In this case I've passed in a parameter age and the default value is 12. Now, remember before how I had passed in the word 20 and it gave us a validation error? But in this case it's fine. Why? Under closer inspection, if we print out the user age, it gives us 12 and the type the string, even though we've specifically asked for an integer. Now that's a huge problem. You can see that Pydantic only validates user input by default, not the field parameters by default. There are ways we can force validation like this. So let's take a look. For example, to fix this, one of the ways, or a really easy way, is to use this parameter called validatedefault, which is true in this case. It forces Pydantic to make sure that this Default value is also the correct data type. Now this is just an extra precaution in case some, someone else or before you or after you might have accidentally changed the code. And you can see it's a precautionary measure. And now if I run this, you can see that we've got a validation error. Why? Because the default value is 12 and you can see unable to parse string as an integer, which input value was 12. So that's how you can use default values and fix this major problem in pydantic. We're now going to be moving on to the next section which is all about aliasing. And I'll see you in the next section. We'll now be moving on to the next section which is all about aliasing. So let's scroll down and we will talk about what aliasing actually means. So an alias is a different name that a model can use to either accept input, which the technical term is called validation, or give output, which the technical term is called serialization. Now this is helpful when the external name is not equal to the internal variable name. Now you might think, well, when will this be helpful? Well, let's explore a real world example. For example, let's say we're working with a logistics API and this is the JSON we've received from the API. The package weight in kilograms, the package destination and package is fragile. But in our Python backend code in Pydantic we have written it as wait, destination is fragile. Obviously they are very similar, but they're not exactly the same and this could potentially throw errors. So this is where aliasing comes in. Hopefully you've understood that this is quite important. So in this case I've going with this example I created a model called package and again it has base model inherited from base model we've created wait, destination is fragile, which is what we had assumed we'd written in the backend code. And you can see now in this case we have added an alias parameter in the field function. Now what has that got to do with all of this? Remember how I had said from the logistics API, this is the data we would be getting. So we've part we've got all of this, but how can we match them or like create like a mapping function or mapping method which knows that, okay, this package weight in kilograms is to weight, package, destination is to destination and package is fragile is to isfragile. And that's where this comes in. You can see that this kind of creates a mapping method from package weight from the alias from the input parameter of the logistics API to our backend code variable name. And we're about to see how it does that. So package is equal to package. And this funny notation. Now, what does this funny notation mean? Now it might look complicated, but it's really just unpacking the dictionary. So this is the dictionary which we've got, and you can see it takes each key value pair and passes them as the named arguments. In this case, it takes this and passes this and like finds out where package weight kilograms is. In this case it's the first parameter and passes the value straight in. So we don't even need to do anything. You can see how many lines of code we've written. Barely any. These are all just print statements. So if I run this, it will start to make a bit more sense. You can see that we've got 4.5, Singapore and True, which are all of these values. And this was the model dump by alias. So let's talk about it a little bit more. You can see that in this case I haven't actually passed it in order. You can see that I've done kilogram first is fragile and destination, Whereas in the actual class the variables will weight destination and it's fragile. So this mapping method, you don't necessarily need to pass the data in the same order as you created in the class. So that's one thing to note. Now if I do it package weight, why dot weight and why not package weight Kilogram is because the internal variable name is weight, not package weight kilograms. Hopefully things are starting to click now. If I do the model dump by removing this line, for example, you can see that we've got it through the internal variables, the weight, destination and isfragile. But if I now create this by alias is equal to true, this is how we'd receive the data. And it's by a package weight, kilogram, packagedestination and packagesfragile. So hopefully that is making sense now. But don't worry, this is quite confusing at first, so let's do some more examples. Let's move to example 1. In this example we've gone back to the student, but this time we're using email as the internal variable. And now I've created the two different types of aliases, validation alias and the serialization alias. So what is validation alias again? Well, this is what is accepted as the input and serialization alias. And this is what's outputted. So the incoming data, in this case, let's say from another API, it's student email and himail.com pretty generic email, right? But you can see that because this variable validation alias, AKA what it can accept as input, is student email, it will go and map to this once we actually unravel the dictionary using this command. So if we now run this, we print student email. After instantiating an object from this model class, you can see that student email is himail.com, the email itself is himail.com because the model.dump we haven't done by alias is equal to true. And if we now print it by alias is equal to true, we get student email, which was this, AKA this. And we will get this. There is one mistake which I just made. This student email is slightly different from this student email. And I made that deliberately because I wanted you to see that the validation alias and the serialization alias is slightly different. So when we do by alias is equal to true true, we're not actually printing the validation alias. We're printing out the serialization alias here. If we've received that, and you can see in this case we've received the serialization alias. So it's a common mistake. I just made that, as you can see. But hopefully things are starting to click now to make sure that this is starting to click more, let's do one more example and let's create a book class this time. So in this case we've created a title and an author. So the validation alias, the serialization alias for both book title, then they're quite similar, as you can see. Now again, we've done a bench data, let's say simple input data. We've received a pedantic guide and the author name is Data Camp. Okay, now we unravel the data again, book is equal to that. Now I want you to take a second and really try to think what all of these will equal to. Once you've done that, unpause this video and see if you were right. Now if I uncomment this and I press Enter and run it, you can see patented guide datacam. The first two should be quite obvious to you because they're, well, just the internal variables. But in this case, title is Pydantic Guide, Author's Data Cam. But the model dump is book title and author name, AKA the serialization alias we had created for all of them, not the validation alias. So just to recap, validation alias, if I go back here, validation alias is the alias which accepts the input AKA for my API. And the serialization alias is what gives the output. What's in our backend code. So hopefully that made sense. You should do some examples yourself and you will become a master of this quite soon. Now if we scroll down, there are some numerical limits which you can also set as well. Now what do I mean by numerical limits? Well, validation doesn't just have to end using just validation, alias and serialization aliases. In fact, these aliasing is a small part of validation as a whole. For example, in validation, what if you're working with integers, you could want a minimum value, a maximum value. You get the point. There's quite a lot of scope here. So in this case we can see that I've created a name, a price and a description. In this case the name I've created the minimum length to be one, AKA the length, the actual name and the maximum length to be 50. The price I've done GT is equal to zero, where GT stands for greater than and description. I have said the default is none, so you don't need to pass a description. But if you do pass in a description, the max length has to be 300. If I run this, you can see it runs flawlessly. Why? Because the laptop is within these limits. 999.999 is within is. Well, it's greater than zero. And this very cool laptop, we've passed in something and the max length is under 300. But now if I do minus nine, you can see we get an error and we scroll down, you can see that the price is where the error has originated because input should be greater than zero because we had set the parameter as greater than equal to zero. So if I clear this now and run this well, you will see that it's right. Similarly, if I had passed in the name to be nothing or the price equal to minus 10 again this will trigger two validation errors. And because pylantic is so advanced, it will tell you each error in a good well mannered format like name and price. So name string should have at least one character and price input should be greater than zero. So it tells you exactly where you went wrong. And that is quite sophisticated as you can see. Now there is a whole host of these parameters which you can add into this field category. And if you want to check them out again, they're all on their documentation. I highly, highly recommend you looking at the documentation as well. Now I have an exercise for you. So this is the exercise. We need to create a book model again, but this time more advanced. So we need to have a title which needs to be a string and it needs to be between one to 100 characters long, it has to have a required author, again, a string. But there's no limit to this. An optional ISBN and a price which is has to be a positive float, which has to be under a thousand units or a thousand pounds, a thousand USD, whatever. And it has to be in stock, which is a boolean value with the default should be true. So pause the video here, try to create this yourself and once you're done, unpause it. Okay, so hopefully you've created it and it works. The solution to this was like this. We create a book class or a book model and we have these parameters, so let's quickly go through them one by one. So we need a required title where we can see that there's no default is equal to none here. And we have done it in the constraints 1 to 100, the author was required as well. As you can see here, there's no is equal to none. For example, the ISBN is optional, so I've passed. In the default to be none, the price has to be less than or equal to 1,000 or greater than or greater than zero. Well, because it can't be negative, right, so. And it has to be in stock, which is a boolean value. So true or false, the default being true. And now if I run this command, you can see that there's no errors and it ran completely flawlessly. So that was all good. There is just one small thing I would like to add here, and that is about ISBN. Now, if you don't read books, that's completely fine, but just for information, ISBN is something called International Standard Book Number and It's normally exactly 13 digits. The reason I didn't ask you to do it exactly as 13 digits was because to include that in our class, we would need to use something called regex expressions and now regex expressions. Some of you might not know it fully. That's why this wasn't a prerequisite for this tutorial. So in this example, if you wanted the regex expression, it would look something like this. Now, it looks complicated and it's beyond the scope of this video, but there are other ways to achieve this, as you can see through this foreshadowing. So let's start to look at that now. So now that brings us to validation once again, and this time we'll be covering a bit more advanced validation. So before we had passed in some parameters and we did some aliasing, but this is really advanced validation. Validation is one of the biggest reasons we use pydantic in the first place. Now we'll be exploring it in this section. So the most important thing which you need to remember here is odelvalidator. So this is a decorator and it's used when we want to validate multiple fields together to perform logic that involves the whole model and to run code before or after normal field validation. That was a lot. So let's try to break this down. For example, if I create an event model, very simple model name start hour and end hour, with the start hour being integer and end our being integer, no fancy like 00 colon 00 for example. It's quite simple. And we're working O clocks. Now if I pass in this event, one is equal to hackathon. Start hour 10, end hour 9. Do you think there's a problem with this? Well, if I pass, if I run this, it's running flawlessly. But there is a logical error here. How can the start hour be before end hour? So the start hour ends is at 10 and end hour is at 9. Now before you say what if 1 is a.m. and 1 is p.m. we're working in 24 hour clock. Okay, so that's a clear logic error. But no matter how sophisticated or how sophisticated your typings or how sophisticated your internal pedantic logic is, this would, this is a logic error and this would work flawlessly. But we need to fix this. And that is where model validator comes in. So if I uncomment this line, let's actually break this down. So model validator is a decorator and in this case I've passed in the mode to be after. Now we'll be looking at this mode before and after in just one second. But if we just skip that for now. You can see that I've created a new function within this class. And this is the check time function. It checks that if self end hour is less than or equal to self start hour. Well that's clearly wrong. Right? How can the end hour be earlier than the start hour? So that's when it raises this value error. So if I press enter now. Well, there you go, we have this error and you can see that we've got the validation error here. And it says value error end hour must be greater than start hour. Please fix this. And this is exactly what I written here. End hour must be greater than start hour. Please fix this. So this is one really easy way to create more sophisticated models, especially when dealing with logical errors. Now if we continue proceeding, we'll talk about now the two different modes, like I briefly Mentioned there is a before mode and then there's an after mode. So before mode, well, it means before validation and after mode means after validation. Now what does that even mean? So I've created this visualization to try to make it a bit more visual and hopefully you understand it better. So let's say we've instantiated the object. Now before the data might still be working, then the validation happens. And then after the data is cleaned and correct to go alongside this, I've created this simple code example. So this is a very, very basic model, the user age integer. Now, user age is equal to 25, but again we've passed it as a string. This was one of the very first examples we had looked at. But now we're going deep into the pytantic process or the internal mechanics. What actually happens? Well, the before. Once you've actually created the object, which is object instantiation, we move to the next step, the before mode, where data might still be wrong. Now you can see before validation age is 25. It's still a string here. So at this point this is 25, aka a string. Then the validation procedures happen, which is the internal mechanics of Pylante. And then in most of the after, where data is cleaned and corrected. So you know how we had discovered that Pyentic has self correction techniques, although basic, but it does have it. All of those happen in this stage, the validation stage, where it's the internal mechanics. So you can see after the validation process, the age is 25, so it's now an integer. So hopefully that made sense. Let's do some practice using coding now. So if I scroll down, this is a before validation example. So the class we've created, the model we've created is called delivery. There's a pickup and there's a drop. So in this case we're going to be using model validator mode as before. So before we had done after, but now we're doing before. A lot of befores and afters, but you get the idea. And also I've used this class method. Now we'll be talking about class method in just a little bit. You can see that again I've created a function and it partakes in a class variable and data. So the print statement I've done just so we can keep track of the process. But, but for example, if the drop is before the picker, that doesn't really make sense again because how can you drop something before even having picked it up? So that's where this logical statement comes in. If that is the case. Well, we can just swap it using this Python function. This is not Python to like internal mechanics, it's just simple Python. Right? And then we can just return the data. And if I create this order one and have pickup as 15 and drop as 13, what do you think the order will be like? It will be like this. So now before validation we saw that the raw input was this, but after validation it was 13 and 15. And that's why it also placed this print statement here, because it's keeping track of the flow. So just to make sure that everything is going fine, look at this, this print statement first. Well, the object is instantiated, which was step one, which is this white box. Then you can see that it went into this model validator process in the mode before. And this print statement happened, as you can see here. And here it was still pickup was 15 and drop was 13. And this was this orange step. But then the validation process happened, which was this custom logic we had created using this. And if we go to the blue state, which is after the data was cleaned and everything, and we scroll down and we get to this place, well, they were swapped. And you can see that the print statement, well, it correctly shows the new model that the pickup was 13 and drop was 15. So to summarize, Model Validator can handle multiple fields, but what if we just wanted to focus on one, that is where Field Validator, another decorator, which is focused on one field. So let's look at that. Now, it's honestly very, very similar. In this case we've imported Field Validator and we've created this. But rather than having a mod, we passed in the price. Why? Because price was one of the variables we had defined as price is float, and in this case we have defined it that it must be positive. Now, yes, obviously you could have done this using a field, the internal field mechanics as well by using greater than or less than operations. But this is just to like home in as to what you could do using Field Validator. So as a simple example, if the value was a less than or equal to zero, we must say that price must be greater than zero and return the value. So let's try it. If we just do price is equal to 10, no errors. But as soon as I do minus 10, well we've got that error and we scroll down, you can see the value error. Price must be greater than zero. So hopefully everything has clicked in. Now that was really one of the hardest parts of Pydantic. So if you understood that very well, Done. And we'll now move to the next section which is called built in types. So built in types, Pydantic ships these helper functions that wrap these common patterns. And this means that we don't need to use regex or extra code. Now this means that it makes development much, much easier and much more efficient. So let's take a look at this built in example from Pedantic import base model. And then I've imported these three. So the best way to look at these built in types is if you come from an AI agent's background or have ever coded AI agents, you're probably familiar these tools or CUST or inbuilt tools, think of these in a way as inbuilt tools. They're not exactly tools, but they are still inbuilt and they make coding much more efficient. Right, in this case we have email string, HTTP, URL and positive integer. So if we create a contact model, in this case, as you can see, class contact, we can do email as an email string, website as that, and follows this positive integer. Why? Because in every email, every valid email needs to be in a certain format. Now we could have defined this ourselves using the field validators, but that's just unnecessary, especially if I can just write this, well, using one command. The same goes with website like HTTP and HTTPs, and the positive integer is quite a common problem. So they've just, rather than having to write the if statement, we can just use this. Now if we create an object and we print this, you can see it runs flawlessly. Because while this is a proper en, this is a proper website, although it might not exist, but it's still in a proper website format and the followers is greater than zero. But now let's play with it. If I remove this, for example, and I remove this and I Change this to minus 10 and I run. Whoa, we've got a lot. And we've got three validation errors. So the input should be a valid URL because, well, it's. There's no HTTP, HTTP or HTTPs, the followers must be greater than zero and the output is truncated. So let me fix those as well. Let's put that and let's put that perfect. And now I run it, we'll only have one validation error left and that was the email. And you can see it's not a valid email because the part after the add sign is not valid. It should have a period. So if I do this now dot com, everything works once again. So that was how you can use built in type types There's a whole host of built in types on their documentation and again I highly recommend looking at that if you're interested. Now let's move to nested models. A nested model is one pydantic model being inside of another model. So this allows us to help organize data cleanly and like JSON objects inside objects. Now this is getting into the more intermediate, advanced level of pydantic. So well done for making it this far. Now let's create two cloud, two models at the same time. So we've created an address model and we've created a user model. In the address model we have street, we have city and we have postcode. Each are strings and the user we have name, email and address where the address is this model you can see it's not a string anymore, it's this model. So that's what we're doing nested. Now let's create our data and let's go this slowly. So we've created a user where the name is Robert, his email is robertmail.com and this address is this street, which I've just completely made it up by the way. And if I now print this and print user address city, what do you think will happen? Well, user is, well this, which is Robert's details, the dot address it comes to here and the dot city part is London. So this should print London, which it exactly does. Let's do another example which is slightly more difficult to really hone this in, where we're again creating two models, lesson and tutorial. But this time we've imported lists. Why? Well, the two models we've created are lesson, where each lesson has a title, a duration, minutes and whether it's free or not, like whether it's paid or not, and a tutorial model where in each tutorial there's a name, the instructor's name and lessons. Now, there can be more than one lesson in every single tutorial. You can think of it as a tutorial or a course, but the point is there's more than one lesson potentially. Now, rather than having to do that, you could have done it lesson one, lesson two, lesson three, but that's just overly complicated and cumbersome. So you can just create a list, for example. Now let's create a data. So the name is learnpydantic, the instructor is me, and the lessons I have created are these three. For example, again completely made up, but the basic models duration minutes, 10 is 3 equal to true, and so on. You can see that these lessons come from this lesson model, because the title, the duration minutes, as you can see, which is highlighted here and is free, is also highlighted here. And if I run this, you can see that the name, the instructor and all the lessons and the lessons come in as lists, each with their separate dictionary. So hopefully that made sense to you as well. Now, there is one more step beyond this, and that is recursive model. Now, a recursive model is very similar to nested models, but you'll see why they're slightly different. The best example for this is a family tree model. And this is quite probably the most exciting model we'll be building. So in this family tree we have two parameters, Name. Sorry, we have two variables, name and children. The name is a string and the children is optional. So why is it optional? Well, optional is a type annotation, which means either the list or, or none, for example, so the list O is a family tree. And notice how there's no second model we've created, it's just referring back to itself. That's where we're doing recursion. Now, when we're making a recursion model, you need to use this familytree model rebuild. Now, this command tells Pydantic to fully build the model after the whole class has been defined. So if we pass in this data, for example, name, root, and the name of this root, let's say the children were child one and child two. Now what if child one had two children? So that would make it grandchild one and grandchild two. But what if child two had a child? It could have been grandchild three. Now if we run this command and model dumb, you can see that it. Well, no errors, but this is not visual enough. So I just created this helper function for visualization purposes and you can see that we have root, we have child one, grandchild one, grandchild two, child two, and grandchild three, all because we had used one recursive model. No, two models. But recursive model is technically kind of like a nested model, very similar. With that being said, that brings us to the end of this tutorial. So massive. Congratulations once again for finishing this tutorial. We've covered quite a lot in this, well, quite relatively short but for beginner level tutorial. So we covered basic models, field types, aliasing, validation, built in types, nested models, recursive models. Now, again, this was a beginner intermediate level tutorial. The main thing to note is Pydantic is really especially useful when you use it in your own applications, especially nowadays when people are using this to define as state schemas in the AI agents. So if you want to learn how you can use this Pydantic in for example Google adk, you can check on the previous tutorial right here on the Data GAM YouTube channel where there were sections where I personally had used Pydantic in the Google ADK videos. There are also other places to go. So for example, if you want a written tutorial you can go onto this URL and there's a whole, whole description of using Pydantic. There are also different courses which you can go to. For example, you can use FAST API for this model validation. And if you want to brush up your Python skills, you can definitely go to this intermediate Python course as well. Hosted on the Data Cam website. With that being said, if you have any comments, feedback, criticism or any questions, feel free to comment down below. If there's anything else you would like to see on this Data Cam channel, then feel free to comment that as well. And with that being said, thank you so much for watching this tutorial and I'll be seeing you in another tutorial. Bye for now. Sam.
More from Richie

#359 My Best Friend is AI with Valerie Tiberius, Professor of Philosophy at University of Minnesota

How AI Agents Will Work While You Sleep | Ruslan Salakhutdinov, Professor at Carnegie Mellon

#358 How AI Agents Will Work While You Sleep | Ruslan Salakhutdinov, Professor at Carnegie Mellon







