How To Create a Python API With FastAPI - Full Tutorial
so what is an API well API stands for application programming interface think of an API like a waiter in a restaurant you the customer requests something from a menu and the waiter or API communicates your order to the kitchen once your dish is ready they bring it back to you now in the digital world an API allows one piece of software to request data from another and receive a response for instance when you check the weather on your phone an API is what communicates between the app and the weather database apis are used all over the place but this video will focus on apis for web applications now most apis interact with data through four main methods collectively known as crud create read update and delete let's break those down create this is done using the post method it's like telling a system hey I want to add something new then we have read this is done through the get method it's basically saying can you show me some piece of information update this involves the put or the patch methods and it's like saying I want to change this existing item to a new value and then delete as the name suggests delete method is used to remove something now each of these methods facilitate a different type of interaction with the data ensuring the Digital Services can manage their resources effectively now when you use an API you make a request to a server this request is your way of asking the server for data or some action the server then processes your request and sends back a response now this response can tell you if your request was successful by using a status code or it might include some of the data that you've asked for now Json or JavaScript object notation is a format for structuring data it's both easy for humans to read and write as well as for machines to parse and generate Json is made up of two basic structures objects and arrays objects are collections of key value pairs resembling dictionaries in Python arrays these are ordered lists of values similar to lists in many different programming languages now because of its structured format Json is widely used for sending data in web applications specifically between apis it's what our API will accept and what it will return now building an API is great and all but it only means something if it's actually accessible online whether you're building a hobby project or you want to actually push something to production you're going to need to deploy it now that's where the sponsor of this video hostinger comes in now hostinger is a super easy to use web hosting platform that offers a ton of different options for any use case now for an API like this we're going to be looking at their virtual private server plans which give us complete control of the server allow us to log in with root access and do all of the advanced configurations that we need for an API like this so if we scroll down you can see that they have really affordable options here and what I'd recommend is checking out their KVM 2 so what I'll do now is Select this plan and just walk you through quickly how you could actually go about hosting this site using host hosting so our first step here is to select our period create or sign into an account and then choose one of the various payment methods and make sure we click on have a coupon code and enter my exclusive code Tech with Tim now once we've done that we'll be brought to a page where we can set up our virtual private server so the first step is to select our location and you can just pick whatever is closest to you for the lowest latency now the next step is to choose our operating system where we have a lot of different options if you scroll down here what I'd recommend for an API like this is using the latest version of auntu so let's select that and now we need to set a strong root password so that we're able to actually sign into our VPS and do the configuration later on so now that our VPS has been set up we can view all of the configuration options and details from this dashboard right here but the next step is to actually SSH into our VPS and configure it for deploying our fast API now this does require a few additional steps that I can't show you in this Quick Clip so what I'm going to do is leave a link in the description that walks you through continuing this deployment regardless you are going to need a VPS to do this so make sure you check out hostinger from the link in the description and use my unique code that you'll have the VPS ready when you do eventually go to deploy this and have your hosted API now for this video we'll use fast API to make a simple crud API fast API is a performant python framework which is easy to learn fast to code and ready for production fast API provides automatic documentation for apis that you write and handles all the complexities of API development for you for example it will automatically convert python objects to and from Json validate different request and ensure the correct data is provided so with that said let's go ahead and get started so in order to get started we're going to make sure we have python version 3.8 or above installed we're then going to open up a new python file in whatever editor we want in this case I've got main.py inside of Visual Studio code we then need to install the different python packages that allow us to use fast API to do that we're going to open up a terminal or a command prompt and we're going to type the following command which is PIP install and then fast API we also need uvicorn and we're going to need pantic so install all of these if you're on Windows you can change this command to Simply say pip if for some reason this command does not work for you then I will leave two videos on the screen that will show you how to fix this and I'll link them in the description on Mac or Linux it's pip 3 and then install fast API uvicorn pantic on Windows it's simply pip so let's clear that and let's close our terminal and now let's write a simple API and see how fast API works so to do that we're going to say from Fast API import fast API and then we're going to create a new instance of this so we're going to say app is equal to fast API and we're going to put a set of parentheses now what we can do is create a simple root I'm going to go through this quickly and then we'll explain it later I'm going to say at app Dot and this is going to be get for now we're we're just going to go with the base root and we're going to define a function now you can Define the function asynchronously like this or you can Define it normally with the function syntax so I'm going to say Define and this will just say read and then what this is going to do is simply return a python object so we're just going to say hello and that's going to correspond with world so now when we go to slash on our API route it should simply just return this data lastly I need to actually run the API so to do that I'm going to say if underscore name equals uncore maincore uncore and then I'm going to import inside of here uicorn and I'm going to say uvicorn do run and we're going to run the app we're going to run it on this host which is 0.0.0.0 and then we are going to say the port is equal to 8,000 and we need to make sure there is a comma there now that's it we've just created our first API here using fast API and the way this works is the following we create an instance of fast API we set up a basic route in this case it's a get endpoint meaning you can send a get request to this URL and then this function will be triggered when this function is triggered we're going to return this python dictionary fast API will automatically convert that into Json data for us then what we do here is actually run the API this line is simply checking to make sure we're executing this python file and that this file is not being imported from some other file we're then importing uicorn uvicorn is a simple web web server that will allow us to actually run this API there's other ways to trigger this but this is the easiest we say uicorn do run we're running this API the host 0.0.0.0 means we're running on our local
IP address and then Port 8000 it's a port where we can access this API so in order to run this now we need to run the python file so we're going to type Python 3 main.py on Windows it would simply be Python and now it's going to start running our server you'll see where it's actually running and you can copy this URL and put it in your browser or you can hold on control and then click it and it should open up in a new browser window let me bring this onto the screen and then we'll check it out so you can see that my API is running we're on Port 8000 and we get the data hello world now where this gets really cool though is that we can go to the/ docs URL and you'll notice that documentation will have automatically been generated for the API that we wrote so we can actually click into this and we can see exactly how this works now what we can also do is we can go to the slash redock endpoint and this is going to give us a different version of the documentation okay so there's two versions you can go to slash docs this gives you this one which is the one that I typically prefer and then you can go to slash redock where you just get a different version okay so that's one of the benefits of fast API the auto documentation but you're also going to see how quick it is to write other types of API endpoints so let's go ahead and start doing that for now what I want to do is build a very simple project where we can have some different tasks I want to represent a database we're going to do that in memory and we're going to have the ability to create different tasks delete tasks update tasks Etc so let's see how we can go about doing that so the first thing I'm going to do here is I'm going to say tasks is equal to an empty list now typically you would connect this to a real database but in our case I'm just going to have an inmemory database which means whenever we turn off the server all of our data will be lost but that's fine because we're just testing things out for now later on you could actually attach this to a real database and then you could persist the data okay so we have tasks equal to an empty list and now what we're going to do is create a model that represents our different tasks now to do that we need to import a few different things so we're going to say from PI dtic import and we are going to import the base model we then are going to say from typing this is built into python we are going to import the list and the optional type and we're going to say from uu ID import and then in all capitals here this is going to be uu ID and uu id4 okay now let's zoom out a little bit so we can read this a bit easier now what uuid means is unique identifier and this is a python function that we can call that will always guarantee a unique ID now what we're going to do is create a simple class and this class is going to represent the objects that we're passing around throughout this API so as I said before we use Json when we are sending data to the API and receiving data from the API and what fast API will do for us is it will take what's known as a pantic model which is what we're writing right now and automatically convert it into valid Json this is one of the benefits of using fast API you can write your code in normal Python and it can automatically be converted to and from the Json data that the API needs so we're going to say class task and then we are going to inherit here from our base model what we do inside of here is we Define all of the different fields that we want to have on our data and we specify what the type of them will be so we're going to have an ID we're going to say the ID is optional but the type of it is uuid and this for now will be equal to none now optional is what we're inheriting here from typing and it just means that we don't need to pass an ID when we create this model next we're going to say title and this is going to be of type string we're then going to say description this is also going to be optional and this is a string as well and then we're going to say completed and this is going to be a Boolean and this is going to be equal to false okay there's a lot more advanced types that you can create here but this is a very basic pantic model notice that we've typed all of the different fields that we'll have here that's very important for doing the correct validation and fast API will handle all of that for us for example when I make this a string that means if I try to create a new task using the API and I don't pass a string the API will actually raise an exception so now what we'll do is we'll write ATA dopost we'll take in SL tasks and then slash this is the URL that we'll go to to create a new task we'll specify the response model which is equal to the task pantic model and that is simply telling fast API that we want to use this model to encode the Json that's returned from this rout we're then going to say Define and this is going to be creatore task you can call this any you want but create task makes sense and that's the name we'll see in the documentation we're then going to say task colon and then task this specifies that we want to accept um an actual new task using this pantic model and that's one of the reasons why we specified an optional ID and an optional description so that when we receive a new task the only thing we need to actually pass is a title so this is the input to the API meaning we need to pass this information with the post request to create the new task then what we're going to do is say task. ID is equal to uyu id4 that's going to give us a new unique identifier and we're going to say tasks. append this task and then return the task okay so you can see how easy this is compared to using some other python Frameworks what happens is any data that's given to us that's valid for a task is automatically wrapped in this task object we then can simply add the ID we can do any checks that we want we can append it into our tasks database which is really just a list and then we can return the task using the response model sweet so that is how we create a new task now just to check if this is working we need to actually write an endpoint that allows us to read the tasks so what I'm going to do is modify this one here so rather than just read I'm going to call this read tasks we're going to make this slash tasks and then slash and by the way it's fine to have the same endpoint here as long as the request type is different so this is post and this is get this time we now need to add the response model as well because we're going to be returning different tasks and the response model this time is going to be list and then inside of list we're going to specify task the reason for that is what we're going to do is return all of our tasks and the type of that is going to be a list type of all of the different tasks so that's why we're specifying that okay so let's save this and let's run our code and make sure this is working so let's go here let me close out of this with contrl c and then I'm going to type Python 3 main.py and let's go to the
docs and see what we get all right so I'm here at the docs now and you can see that we have read tasks and we have create task if we click into read tasks we can actually click on try it out and execute and you'll see that it just gives us an empty list because we don't have any tasks whereas if we go here to the post and we click on try it out we can see an example of how to create a new task so I can remove the ID because we don't actually need that and let's give it a title of hello world and a description of testing and click on execute and as we go down here you're going to see that it gives us a status code of 200 this was actually the response which is now the new task and notice that it's added the ID for us and it says this was a successful response so now if we go back here and we execute this you'll see that we now get the new task that we created now one thing to note here is that if we tried to maybe send some invalid data here so create a task that has no Fields you'll see when we do that it tells us 422 error unprofitable entity the reason for that is that we did not pass the fields that we need and you can see there's some information provided here like a field required missing Etc okay so it automatically did that for us we didn't need to write that code the validation was provided by fast API so let's go back here and let's write a few other endpoints and let's create this entire project so there's three more end points that I want to write here the first one is to view a specific task TK then we want to delete a task and we want the ability to update one so I'm going to do the viewing a specific task first I'm going to say at app.get and we're going to say slash tasks slash and then what we're actually going to take in here is inside of curly braces the task ID now this is how you have a path parameter sometimes you want to have a dynamic value in the path that's exactly what we're doing now same thing as before we're going to have the response model equal to task we're going to say Define get underscore task or actually we can say read task because this one is read tasks plural then inside of here what we need to take is the task ID we're going to say that this is of type uu ID and that's going to correspond with this path parameter okay then what we'll do inside of here is we'll say for task in tasks we're going to say if the task. ID is equal to the task ID that was passed in the path parameter then we will simply return the task otherwise we're going to return and before we can do this we need to import it so let's go to the top of our program and this is an HTTP exception let me see if there's an underscore there or not I don't think so I think that's good and we're going to return HTTP exception and for the exception we're going to say the status undor code is 404 which stands for not found and we're going to say the detail or the error message is Task not found okay so this is how you can return a custom error we're saying okay well we didn't find the task we're looking for so we're going to raise an exception the status code is 404 and this is the error message we're going to give you okay that will allow us to read an individual task based on its ID next what we want to do is update a task so to do that we're going to say ATA Dot and then we can use put or patch in this case I'm going to use put now for put what I want to do is slash tasks slash and then same thing we need the ID of the task that we're going to be updating so we going to say task task uncore ID I'm then going to say the response uncore model is equal to my task then we're going to say Define update task like before we're going to take in the task ID but we're also going to take in the new Fields so we want to update the task with so we're going to say task undor update and then this is going to be task so what we're going to do in this function is similar to what we did before we're going to look for the task that has this ID and then we're going to update it so we're going to say four idx comma task and this is in enumerate and we're going to enumerate over all of our tasks the reason we're using enumerate is we want the index as well as the task then we're going to say if the task. ID is equal to the task uncore ID then we will perform the update so to do that we're going to say the updated uncore task is equal to and I'm going to write some fancy python syntax here this is going to be task. copy then update is equal to task underscore update if we can spell that correctly ditionary and we're going to say exclude uncore unset equals true now what this is going to do is it's going to look at the task update so whatever the new fields are that we've passed for this task because again we're updating an existing task we're going to get the dictionary representation of that and then we're going to exclude any of the fields that are unset so an unset field is something we didn't actually pass so for example if we didn't pass the description we're going to exclude that when we update this task this is a fancy way just to update the task using the pantic model don't worry about it too much it just updates and gives us a new task that has all of the fields combined from this one and the update and it will use any of the update fields and override existing Fields if both of them exist okay then what we're going to do is say tasks at idx is equal to the updated task okay so we're just replacing that pretty much and then we're going to say we're return the updated task okay now lastly here we're going to say raise and this is going to be HTTP exception we're going to say the status code is equal to 404 because again we didn't find this and we'll say the detail is equal to task not found now that reminds me up here I was returning this I actually need to raise this we raise the error we don't return it and then fast API will automatically handle displaying it to the user okay the last one we need to write is our delete method so we're going to say at app. delete we're going to write slash tasks same thing we need to have the ID so we'll say task ID the response model again will be equal to the task let's make it so we have a bit more room and we're going to say Define delete undor task and then we're going to take in the task ID okay how do we do it this time well we're going to say for idx task in enumerate we're going to enumerate over all of the tasks then what we're going to do is say if the task.
ID is equal to the task ID then we will return the tasks. pop okay and we're going to pop on the current index where we found that task and then otherwise same thing let's just copy this we're going to raise that HTTP exception so the idea here is again we're looking through all the different tasks we're getting their index and what the task actually is if the task ID matches the ID we're looking for then we know we found the index where this task exists so what we can do is pop it which means we are going to remove and return it from the list which is exactly what we want to do now if we get to the end here and we don't find the task that means the task did not exist or this ID was not in one of our tasks so what we do is we raise this exception perfect so that pretty much completes this program now all this left to do is to test it out and by the way all of this code will be available from the link in the description in case you want to have a look at it so let's clear our screen and let's run and let's go over to our fancy documentation and let's see if it works now so notice we have delete task update task read task create task and read tasks we need to make a new task here so let's just use the sample one uh let me just refresh here okay and we're going to go try it out we can remove the ID D cuz that's going to be automatically generated for the title we'll just go with task one and we'll go task one description okay let me copy that and execute looks like this was all good okay let's make another one so let's copy this here and go task 2 task 2 description execute and let's just make one more and this time we'll make it completed okay execute there we go now let's go to read tasks let's try it out and execute and you can see that we have our three different tasks perfect let's go here to read an individual task uh we're going to need the ID of one of them so let's find one of the IDS okay let's copy that go back here and try it out let's pass in our task ID execute and you can see that it gives us our task perfect let's try to delete a task so let's go try it out paste this in and execute and we can see that it said task not found okay so that potentially an issue let me see why we got that all right so a silly mistake here but I forgot to specify the type here for my task ID which needs to be uu ID so because I forgot that we were getting an issue when we're actually searching for that task but now that I add that we should be good to go so we can test that out one more time by just closing and rerunning and let me just get back to that same example all right so let's go to delete the task now after I've made that fix and when I click on execute it says yes it's good to go it deleted successfully and it Returns the task that I deleted now if I go back here and I go to execute you see we only have two tasks left let's copy one of their IDs and let's try to update them so we can go to update we can pass in our ID and here what we need to do is we need to pass completed and title but we don't need the description or the D because if we go back to the code we can see in our task that these are marked as optional so when we do the update we do need to pass the title and completed if we didn't want to have to pass those we could mark them optional and then we wouldn't need to pass them when we performed the update but you'll see what I mean here so what we can do is remove this and for the title we can just make this new title and we can make completed equal to true and when I click on execute here you can see now that it marks complete true description is the same as before and the title is the new title all right so there you go you have now learned how to use fast API to create an API in python as fast as possible it's really cool that it gives us this documentation it also makes it really easy to test and play with our API and obviously there's a lot more advanced stuff that you can do this was really just meant to scratch the surface and show you how quickly you can actually get this up and running if you enjoyed the video make sure to leave a like subscribe to the channel and I will see you in another one [Music]
2024-05-29 17:34