Python REST API Tutorial - Building a Flask REST API

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
[Music] hello everyone and welcome back to the YouTube video so in today's video what we're gonna be doing is building a RESTful API in Python using the module called flask now for anyone unfamiliar with flask and not only can you make websites with Python using flask but you can also make rest api's which is what we're gonna be doing in this video it's really known for making micro web services because it's a very lightweight module it doesn't come with a ton of things in the box but for our purpose that is perfect because there's a lot less setup we need to do and it's really fast only a few lines of code to actually initialize flask and start using it to make an API now for anyone's unfamiliar with the term rest or the term API I'll quickly define them for you so rest stands for representational state transfer you'll see why that's important in a second and API stands for application programming interface essentially what a REST API is is a way for other programs or applications to manipulate or query or update or delete or whatever it may be information so it's a way to deal with some kind of data in a structured format now what I mean by that is essentially we set up this API that has a bunch of endpoints now these endpoints are essentially almost like commands or you can think of them as just requests and when this endpoint gets hit when someone hits that endpoint so they go to it they connect to it they send a request to that endpoint that endpoint will return a response based on the request that was given so for example if the request was give me all of the views that are on a specific video then the response would be the number of views that were on that video let's say that video didn't exist then maybe the response would be something like 404 you know not found right we could not find what you were looking for so that's just a very basic example the reason I'm bringing up that is because what we're actually gonna be building in this video is kind of a mock YouTube API this is gonna be very minimal obviously not gonna have all of the features of YouTube we're gonna be dealing with channels and videos and essentially coming up with some kind of API REST API that can not only create new videos but can give us information about videos can delete videos can update them and can link those videos to channels so we're gonna start by building a very basic API that just does something like return information to us and then we'll make one that actually allows us to create new information update information will then put that into some kind of database then we'll deal with custom objects and while this video will be long but it will cover pretty much everything you need to know to actually make a fully functioning web service and restful api so with that being said let's go ahead and get started so before we can actually get started writing any code we need to install some requirements in our Python environment now if you guys are experienced with this I'm going to assume you already know what to do I have a requirements txt file in the description right now you can go ahead and download that and simply install that but for those of you that haven't used pip before or you just don't know what I'm talking about essentially what we need to do is install some Python modules and we do that through a command line tool called pip now by default pip should be installed in your system and you should be able to use it you can use pip by typing pip in your terminal or in your command prompt we're by typing pip 3 now for some reason this doesn't work first make sure you have Python installed and if you do have Python installed and that's not working you need to configure pip on your system so that it's working correctly so I'll leave a link in the description as well as a card in the top right hand corner follow along with that video it's titled how to install PI game but that will show you how to fix your pip now once that's working we need to install three things we need to install flask flask restful and the request module now to keep this easy for all of us what I would like you guys to do is go to the description and click on the link that says download requirements txt or there will be something that says requirements txt that should download this txt file for you and I want you to put that in the same location as where you're gonna be writing your Python code so in some kind of folder or some area that you can easily find you know maybe on your desktop or something like that so once you have this file requirements dot txt that has this content in it here in some location on your desktop or somewhere that you can find it what I want you to do is navigate to that from your Windows Explorer or from Mac OS so I'll just say both ways here but I am on wind so I'm going to illustrate how to do this so you can see that right now I've navigated into the folder that has my requirements txt now a shortcut to open up the command prompt in this directory is to type CMD you write in this little bar up top so delete everything there and type CMD and notice that when that opens CMD the path that's right here that I'm highlighting will be the path to the requirements txt file this is the goal you just need to make sure this path matches you can also do use something called change directory so change directory will allow you to select the folder or the location that you want to move to so if I say CD and then I type flask rest api tutorial like that I've gotten through those options by hitting tab you can see that it will move me into that folder and now I'll be in the right location so just make sure this matches if you're on Mac and you've navigated to the right location what you can do I believe is right-click and click open terminal or something like that and then you should be in the correct location to be able to do this otherwise just use change directory from opening up terminal to get into the correct directory where your requirements not txt file is and then you should be good to go so now what we're gonna do is type pip or pip 3 depending on if you're on Mac or Linux or Windows then type pip install - are and then requirements dot txt so this is the command you might need to change this again to pip 3 if you're on Mac or Linux and then go ahead and hit enter what this will do is take all of the lines that I have inside a requirements dot txt and automatically install that module into your Python environment this way we're all on the same page we're using the same versions and hopefully everything should be ok so anyways once you've done that we're good to go let's go to an empty Python file you can just make one I'm gonna call mine main top PI and let's start actually writing some code so please just make sure that you have all of those installed again that's flask restful flask and the request module ok so the first thing we're gonna do is we're gonna say from flask import flask with a capital F and then we're gonna say from flask underscore restful imports API and import resource now these are the two main things we need to use are the two main modules we're gonna be using here we'll import some other things but the first thing we need to do is actually create an app which within flask so this is common this is what you usually do when you make a new flask app you say app equals flask and then underscore underscore name underscore underscore so there's two hundred scores there make sure you don't miss that and then next we're going to type API equals API and we're gonna put app inside of here this is pretty much saying we're gonna wrap our app in an API and this just initializes the fact that we're using a restful api once we've done that what we're actually gonna do is we're going to go down to the very bottom of our program and we're going to save underscore underscore name underscore underscore equals equals and then in double quotation marks underscore underscore main underscore underscore then we're gonna say app dot run debug equals true this is gonna actually start our server and start our flask application and the fact that debug equals true will say that hey this is in debug mode so we're gonna see all of that output and any logging information so if anything goes wrong we'll actually know why if you're ever running this in a production environment please do not run with debug equals true this is only when you're running in a development environment and you're testing things like we are right now okay so once we've done that just gonna open up a command prompt window here I'm gonna go and I'm actually gonna run this main dot Pi application and make sure that this is working now you can run this from wherever you'd like but I'm just gonna run mine using Python main dot PI I'm doing this from the command line and you can see that I'm in the right directory where that made-up high script is so running Python main top I will actually use Python to run that file again if you're on Mac or Linux this might be Python 3 really depends so now we can see it says running on HTTP 1 to 700 1 colon 5000 so this is actually the URL that our server or our API is currently running on so this means that whenever we send a request we're gonna send it to this location right here and then whatever else going after the slash so this is just your localhost location you can change this if you want but just make sure this is working first and that we should be good to go ok so now that's working what we're gonna do is we're gonna continue and we're actually going to make our first what we call resource within this API this is pretty easy to do what we're gonna do is make a class we're gonna call this class whatever we want whatever we kind of makes sense whatever information it's gonna return to us and in this case I'm just gonna call mine HelloWorld now this is just a basic example we'll get more complicated later but inside of HelloWorld what we're gonna do is we're gonna inherit from resource essentially what this is saying is we're going to make a class that is a resource and this resource will have a few different methods that we can override on it that will let us do things like handle a get request handle a put request handle a delete request that is what we write inside of here so don't worry if you're not familiar with classes but the idea is we define what we call get inside of here so I can define get like that and I can put self in here and then this is what will happen when a get request is sent to a certain URL that we'll talk about in a second so anyways we're going to define get an inside of here all I'm gonna do right now is return a Python dictionary that simply says hello world inside of it like that now again this might not be completely valid but it's totally fine it's just for this example what I've done is made a resource called hello world we've overridden the get method which means this is what will happen when we send a URL our sunday get requests to read to a specific URL and then when that happens we're gonna return the information hello world so let me go here now and what I'm gonna do is actually register this as a resource so I'm gonna say API dot add resource and then inside of here resource I'm going to put the name of the class that I want to add so essentially what I'm saying is since this is a resource let's add this to the API and let's make it accessible through what URL so right now I'm just gonna put slash which just stands for default URL but let's say we only want to access this when the user types hello world it sends a request to hello world then I would use hello world as my endpoint here so essentially we're determining what the root of this resource is gonna be so how do we find this resource when we send a request you know the server that we're running on so that's what we're talking about here so that's what we've done we've said API dot add resource HelloWorld and we've said that's gonna be accessible at slash hello world what that means is if we send a get request to slash hello world it should return the information hello world so to actually test that what I'm gonna do is make a new file and I'm gonna call this one test dot py go ahead and do this as well if you'd like to you can also do this in a Python interactive console but since we're gonna do this a few times I'm gonna make it in its new file and what I'm gonna do inside of here is actually send a request so I'm gonna import the request module from Python this lets us send you know post request put request get request whatever it may be and inside of here I'm gonna define first of all what our base URL is gonna be which is 80 HTTP colon slash slash 127.0.0.1 colon 5,000 slash and that's what my base URL is so that essentially is the location of the API that's the server that it's running on and recall that we got that because we were looking here and it said running on this is what you want to put where you where I'm putting base here that's essentially what we want now what I'm gonna do is I'm gonna say response equals requests dot get and inside of here I'm gonna put the base URL plus hello world essentially what I'm saying is I want to send a get request to the URL that is base plus that so we'll send it to that slash hello world and then I want to take that response and what I wanted to do is I actually want to print the response dot JSON now the reason I have to do dot JSON is just cuz I need this to not look like a response object and to actually be some kind of information so this dot JSON method will do that for us so let's actually go ahead and see what happens when we run test stop hi the way we're gonna do that is just by running to command prompt windows here so I'm gonna start by running our API are running our flask server and then I'm actually gonna go ahead and run this test dot PI and I'll show you what happens and we seem to have gone an error here object of type set is not JSON serializable I know the issue here that was my bad sorry inside of this here what we're gonna do is instead of just having a hello world we're gonna say Dada : hello world so I just need to make a key value pair here whether you're returning from the get request I thought we would have to do that but I wanted to try with just the whole world so anyways let's give this a shot now so I was just watching back the video while editing and I realized I missed out on a pretty important explanation so I wanted to patch it in here essentially what I want to say is that every time that we return some type of information from our API we need to make sure that information is serializable now that's a big word a lot of people probably don't understand what that means but you're gonna see that when I pass information back or return information sorry I'm doing it inside of a Python dictionary now the reason for that is because this kind of represents what we call a JSON format now JSON is just literally Python dictionaries you have keys and you have value so you'd have something like data that could store another dictionary and then inside of here you could have like name and that stores Timm whatever right this is like a JSON format and essentially we're gonna be returning JSON serializable objects so what we need to do is make sure we're returning Python dictionaries or something else that is serializable so just so you understand and you realize that I can't just simply return the string hello world actually that will probably work but there's a few things that I just can't return from my API or that will give me all kind of errors because they're not JSON serializable so just ensure that when you're returning something from your REST API its JSON serializable if you don't understand what that means you can look that up but the rule of thumb is if you want it to work just use a Python dictionary like this make some key and then have some value and you should be good to go my apologies for not having on the original video but hopefully that clears it up for any of you guys that are wondering as we go through so let's go back here I think the server's still running and by the way when you run the server in debug mode when you save it automatically updates so that's why that's happening we're gonna Python test on pi and now we'll see what we actually gets when we refresh this so we can see that what that actually returned to us over here is data hello world and it showed us that there was a get request sent to slash hello world and 200 which means okay so when he see a status 200 that means everything was okay nothing crashed now I can do this as many times as I like right I can keep her running these requests and every single time that I run Python testify we're gonna get a result that says data hello world perfect there we go so that is the basics of making a flask API of course we're gonna continue but that's how you make a resource you go ahead you define a resource like that you override whatever methods you want to happen on this resource so in this case we want a get method and there you go when you have send a get request it will return whatever you go ahead and put here now let me go back to test op pie here and I want to show you what happens when I send a post request rather than a get request so let's go back to our command prompts the server is still running as you can see there I'm gonna run Python test stop hi and notice that what it says here is message this method is not allowed for the requested URL so we actually got an error that was automatically handled by flask that told us hey no you can't do that we don't have a post method overridden here on our main DUP hi I'm sorry in our hello world resource so that doesn't work but if I go ahead here and say define post and I put itself and let's just return this same information here it's actually returned data and we'll just say posted like that and let's see what happens now when we actually run this so let's bring this back up Python tests up hi and there we go we get data posted so when we override the correct method and use the correct method we're good and that works okay so now what we're gonna do is we're actually gonna deal with storing data on the server and understanding how we can pass information through the request because it's not extremely useful to just get back some dictionary like this that just says data and then whatever information is here what we probably want to do is return some specific information or we want them to ask for some specific thing right they're probably not just gonna send one general request that can give them everything they want so what I'm gonna show you now is how we can actually pass arguments or pass kind of parameters through the request URL so if I look here at slash hello world what I can actually do is the a parameter that I want to be passed in now to do this what you do is use these angle brackets like I have here you define the type of the parameter that you want to come in in this case I'm gonna say string but you could do int like that if you wanted to I believe you can do boolean as well but I'm gonna put in Slyke this or so not in string defining that hey I want this parameter to be a string I'm gonna put a colon then I'm gonna define the name of this parameter which in this case I'm just gonna say is name what this essentially says is I want the user to type some string after hello world we're gonna pass that in to our request here so in this case I'm gonna go and I'm gonna say name like that and what that means is now inside of this get request I'll be able to access whatever name they typed here and I can do something specific with that so right now all I'm gonna do is just return that name back to them just to show you how this works but the idea is that we can create parameters and technically I can make another parameter if I wanted to okay go ahead and do int and just say you know test or something like that and I'll actually show you how this one works now we have a name and we have test and I'll just go and I'll say test and we'll just put tests like that and so data actually let's just put name and then this way we can see which what these two are so now if I want to send a request to hello world I need to pass not only a name but I also need to pass some numbers for tests so I'm just gonna go Tim and I'm gonna go nineteen just going with my name and my age all right so let's go ahead and do that and let's run these two things now and see how this works so we can see that the server is automatically refreshing because it's in debug mode so I don't need to run that again now I'm gonna go to Python test stop I just refresh that there and oops we can't use a post request anymore we need to use a get request my apologies on that so let's go back here and run this one more time okay so python test op pi we get named Tim test 19 because that is the information that we sent and that was the information we got back so that is the basics of making parameters inside of here again the reason we might do that is that we can have the user kind of ask for one specific right so now they're gonna pass hello world let's just keep it at name for now we don't need anything else and what I'll do is I'm actually gonna make an object up here that says names okay so I'm going to say names equals and we're just gonna make a dictionary and what we're gonna get the user to do now is when they send us a name we'll return to them any information relating to the name that they asked for so let me just go inside of here and let me go Tim and let's just go : and let's make another bit of information here we'll say age 19 we'll say gender male and then what we'll do is we'll discuss that's not what I wanted we'll make another one here so let's say instead Tim will say bill will go age 70 and we'll go gender male again so what I'm doing is just putting some information inside of a dictionary here that we can access and now when they say get what I'll actually do is I'll return names of name like that so now we'll take whatever name they pass in and we'll give them some information relating to that name so let's go to tests now let's change this dust to be Tim and let's now test this out and see if this is working so if we go here oops let's go python name male is not defined oops I need to put that in a string my bad guys so male needs to go inside of quotation marks like that okay so now we should be good to go let's see if flask server is running okay we're good let's run test up high and there we go we get information so he had age 19 gender male now let's go ahead and change the name here and set a Tim to be built oops not nil I want that to be built then let's run this now and we can see that we get age 70 gender male so that is the basics of how that works in terms of passing parameters and returning information now we're gonna start kind of creating what I was talking about before which is this video system or this YouTube kind of like program right or API or whatever you want to call it so setup hello world now what I'm gonna do is I'm actually going to make another class and I'm gonna call this class video this is gonna inherit from resource again and we're gonna have a get inside of here that has a self and a video underscore ID now what I'm gonna do is instead of names I'm gonna go here I'm gonna say videos equals and we're gonna make a kind of empty dictionary like this is gonna store all of our videos now what I'm gonna do is I'm gonna say return videos of video ID so essentially when you send a get request to whatever URL that we're about to define here you will get any information about the video that has the video ID that you asked for so what do we need to do then we need to add a resource to our API so we're going to say API add resource the resource is gonna be video and the key is gonna be slash video slash int : video ID there we go so now whenever we send information to this request we need to pass a video ID and we'll do something with that now instead of just having it get though what I actually wanted to is I want to make a way for us to create a new video so we're gonna say actually put right here so define put we're gonna say self and video underscore ID as well and now what we're gonna do is we're actually going to create a video inside of this put now how are we gonna do that well what information do we need for a video first of all that's the first thing we need to define is kind of like okay when we make a new video what do we need about that video are we gonna have something like the views the likes the dislikes is that information we want to store do you want to store how old it is what time was uploaded out all of that right how do we do that well this is where we're gonna start talking about something called argument parsers now the first thing I'm gonna do here so I'm just gonna go ahead and just write a return just so we have something going on here but we need a way to essentially create a new video so we're gonna make it so that they have to pass certain information that's not actually inside of here so not right inside of the URL but inside of the data so when you send a request let's go to our test script here what you can actually do is if ice changes to say a put request I can pass data in the form of say JSON or some other format here that will actually get sent alongside of my request so rather than just having all the information we want stored directly inside of the URL which anyone can kind of see and look at we can send information through data so I could send something like likes 10 like that and essentially I just want to show you the way that we can actually get data from a request like this right so if I'm sending likes 10 how do I actually get this information in my request over on this side well the way you do that first is by importing request up here so from flask excuse me import flask comma request now request is the request object can be used inside of resource and essentially what it will do is give us any of that information so it can give us stuff like any of the data that was sent here there was some other things we can access on request too like the method for example lay my type request dot and I believe method that will tell us that this was a put because while we're inside of the put class are inside the put method sorry but anyways if I want to look at the data that was sent what I'm gonna do here is just print and we'll just say request dot form now that data that we sent here comes in what's known as a form and we can access the likes we can access any of the other keys here by doing something like request dot form and then putting likes here now what that will do is give us the value 10 because we sent a form that has the key likes associated with the value 10 so hopefully that makes sense but I'll just print request stop forms you can see what it looks like I mean you can get the idea of that is actually how this information is being sent this is the server on my left I'm gonna run this sometimes I have to just click over here to get this to work and we can see a mutable odd yeah immutable multi dict and we have likes comma 10 showing up here so obviously not a format most of us are probably familiar with but it does store that information and again if I wanted to that I could use likes now that's fine that's okay but it's actually a lot easier way to do this rather than use requests in fact flask restful comes built-in with this thing called a request parser which essentially makes sure that when we send a request we pass the information that we need with that request so what we can do is we can actually say video underscore put underscore I'm just gonna call this args equals requests a parse like that dot and then in this case it's request parser now we just put the brackets like this here to instantiate that but what this is saying is we're gonna make a new request parser object and what this request parser object will do is automatically parse through the request that's being sent and make sure that it fits the kind of guidelines that we're about to define here and has the correct information in it if it does it will actually allow us to grab all of them information really easily by using a method called parse args you'll see that in a second but just follow along with me here the idea is that say every time we want to create a new video we want to have three different fields so we want to have like the likes we want to have the name of the video and then maybe we want to have I don't know what else did we have on here the views how many views are on that video well if we want to make sure that these three pieces of information are sent to us we need some way to validate that right so this request parse here that we're using so video put args is gonna do that for us so what we do is we logo video put args dot add argument and what this says is this is one more thing that we want this is something we need to be sent with it so what we're gonna do isn't put the name of the argument which is essentially going to be the key that needs to be sent we're gonna put a name we'll put the type that we want this argument to be in this case I want the name of the video to be a string so I'm going to put STR we're just writing Python datatypes here so you could do in string boolean so on and then you can put a health value and what the health value says is what we should display to the sender if they don't send us this name argument so it essentially is like an error message that we're gonna put here so we'll just say this is the name of the video so this is going to tell us the hey you didn't send name this argument is the name of the video you need to send it and flask will automatically handle sending air requests to the sender if that occurs if the request parser does not find the arguments that we need so what I'm gonna do now is just copy this and I'm just gonna paste it two more times because what we're gonna do is we're gonna now have names are sorry not names we're not name views and likes as mandatory arguments and now these are gonna be both ins and we're just gonna put to name a video will say views a video and I will just say likes on the video views of the video likes on the video yeah that makes enough sense to me okay so now we have a request parser that has these three arguments that are mandatory to be sent these are the types of the arguments and these are the help strings that will show up if we don't send that valid argument so now inside of put what I'm gonna do is I'm gonna say args equals and in this case we're gonna do video put args dot parse args now this is gonna get all of these arguments that's what args stands for arguments from here and if they're not in there so if they weren't sent it'll automatically send back an error message so what I can do now is just print out args or actually let's just send a response back that is video ID : args I won't be able to have a look at what args actually is yeah so that should be good for now we'll get it to add into videos later but I just want to make sure that this is working for us before we do anything else so now when we send a request I'll leave it like this for now to show you what happens when we send an invalid one and then I'll send a valid one after so you notice that we didn't send anything to do with views or do with the name of the video we just have likes so loop so I could open this up okay let's have a look at this now so Python test stop hi and whoa what happened we got a huge ton of errors well that is because first of all we did not send the correct thing forcibly close let me send that one more time there we go okay so now we get one name and none views none likes 10th okay so sorry I don't know what happened up there I think it's just because the server needs to refresh but the idea is this was the response that we got when we didn't send the name and the views now the reason that didn't crash is because we didn't make these arguments required which I'll show you how to do in one second but notice that that argument parser automatically made these none because we didn't send anything with them and it made likes 10 so the response from our API here was the video ID args inside of a dictionary and args of course was a dictionary that had those arguments now let's say we actually want this to crash when when we don't send the correct arguments then what we need to do is make this required so you can say required equals true inside of all of these add arguments and this will make sure that now instead of sending that valid response back with none as the key for all are known as the value for all those keys it will actually just crash or it'll show us an error message so let's run this now and notice we get message name name a video so this is pretty much telling us hey you know this was the argument that you sent this was invalid right this just didn't happen and in fact inside of this health up sorry help string here what we should probably do is say name of the video is required right just to make sure that they actually understand that but anyways you get the point what it is it sent us a message that said hey you know name this is the key or the argument that we're looking for and this was the help string associated with it and we would not have created a new video if that had happened so anyways that is kind of the basics on that now that we understand how that works let's actually start adding videos and then being able to get videos making this a bit more functioning and then we're talking about delete videos and add a few other things as well so the first thing that we're gonna do here is we're gonna add a new video in from the put request so let's say args are valid we don't get that you know error message happening then what we're gonna do is we're gonna save videos video underscore ID equals arcs now since args is a dictionary of its own it's totally fine to just do that and now what we can simply return is just ID whenever we want here actually so I'm just gonna return videos video underscore ID and what I'm gonna return beside this is actually a code so what you can do if you want to return a specific status code to the person who's sending the request is inside of the return statement after you return the data that you want you can simply return some coat so 201 stands for created so I'm gonna send 201 as a response back so that they can see that hey you know this was created that work fine you don't have to send these by default it sends what's known as 200 which is the one for okay which just meant you know nothing broke there's but there's a bunch of other status codes that you could send depending on what you're doing so I'm gonna send to a one to show the person that it was created and let's go ahead and test this now because now we can actually use a get and put request and we can see how they work together so what I'm gonna do is say response equals request stop put will print out that and then I'm just gonna copy this again and I'm gonna put an input in between so we can kind of pause it and I can press ENTER first and now I'm gonna actually send a get request and I'm gonna look for video slash one so the idea here is what I've done is I've said whatever video ID they pass here in the put request like as the actual what do you want to call it argument or as the parameter whatever it is in after this slash we're gonna make that the video ID so that's gonna be the key inside this dictionary and we're gonna associate that with the arguments that they pass as kind of the data right that was sent and then that way we can return what if they have the video ID that video ID back to them and since they created it they wouldn't know what that video ideas so anyways that's fine we'll just do that and let's go and have a look at this okay so now the service should be running we'll run Python tests up high we get message name a video is required ah forgot about that's good job we have those messages because I need to add a name which we'll just put as Tim and then we need to add views which we'll just put as you know a hundred thousand for right now so let me refresh this one more time okay oops server crashed on us they let me just rerun this is cuz the key didn't exist that's fine but let's go Python test up hi now we can see named Tim views 100,000 likes 10 and I'll press enter and we get named Tim views a thousand likes 10 the reason that's meaningful is because I sent a get request that get requests asked for ID 1 and that returned to us whatever was stored inside of videos that had ID 1 ok so I'm confident that most of that is working now the next thing I want to do is actually fix this error that we just ran into over here there would this a whole big whack of code that was happening in this key error 1 and I want to make sure that we actually don't crash if we ask for a video which ID does not exist right because if I try to access video ID 1 from videos and it's not there then of course our program is gonna crash so how do we avoid that well what I can actually do is define a function I can say abort if on your score video underscore I ID doesn't exist this is a long name for function you can use whatever you want but I'm gonna say abort if video ID doesn't exist I'm gonna put video ID in here and what I'm gonna say is if video ID not in videos which is the variable we're using to store the videos then I'm gonna say abort like that and what I'm gonna do now is import abort from flask restful abort essentially will send an error message back saying whatever you put here so we're gonna say video ID is not valid dump like that so essentially this will just abort so whenever you see the abort function like this whenever that is called it just immediately returns a response back that says hey this crash this didn't work so we can just call abort like this and that return statement will be skipped so just keep that in mind so what I'm gonna do now is inside of guest I'm gonna call our guest inside of get I'm gonna call abort if video ID does not exist and then inside of here I'm going to simply put video ID and that should be good so this will make sure that that video the ID exists before we actually go ahead and do that return so we can avoid crashing the program so let's go back over to the server now and to our test script and let's go and let's go test let's get rid of this first one here because we don't need that we can get rid of the input and let's try to look for a video ID 6 and see if what happens now if we do that so obviously video ID 6 doesn't exist so if I run Python test op pi what happened here we got some kind of error let me just have a look here alright so I noticed the error here I forgot that I actually need to send what's known as a status here so before I can actually send the message which is this which I'm actually gonna define by saying message equals this is correct now we need to send a status code so if we abort we need to send a status code 404 stands for like could not find you and you see 404 page not found we're gonna say message video is not valid or we could say could not find video now to give you an example of some more status codes there's a status code 409 that that means video already exists or you like thing already exists I'm just using video because that's our example there's a whole bunch of other status codes and if you want to know them I'd recommend you look them up so anyways let's run this one more time it's common to make a few errors here go python test op pi and now we get message could not find video status code 404 which we can see right here so that's good now so now we have video kind of somewhat working the next thing I want to do is I want to implement another method for deleting a video and I also want to make sure that we don't create a video that already exists so let's go with the leap video first I'm just gonna define delete notice that the name of my methods match the HTTP methods that I'm accommodating so we have get put delete you don't have to use these for what they're actually meant to do if that makes sense but that it just it's common practice to use put to create something to use delete to delete something and use get to return something there's also one called patch that we'll use later which allows you to update something so I'm going to say delete self and then what we're gonna do in here is we're gonna say video underscore ID and what we'll do is we'll make sure that this exists so first I'm gonna make another method here and say define abort underscore if underscore video underscore exists and inside of here I'm gonna say video underscore ID I'm gonna say if video ID in videos then will abort we're going to abort with a 409 status code which stands for this already exists we're going to say message equals video already exists with that ID and we'll do dot dot dot for that as well oh so now what I'm gonna do is inside of put sorry I'm gonna put a bort if video exists so abort if video exists like that we'll pass the video ID this is just to make sure that we don't create a video that already exists right so we're gonna abort if it exists and then inside of delete I'm gonna say abort if video doesn't exist if I can find where that one was abort underscore if video ID doesn't exist video ID then if it does exist we're gonna say Dell videos video ID and then we can simply return this comma 204 204 stands for deleted successfully so this is just a blank string I don't want any message I just want to send a status code to of for this essentially says hey that worked you were able to delete this okay so now that we have that things are looking pretty good let's do a few tests here with some different requests and just make sure that everything seems to be okay so let's do one here response request up put let's put video with ID let's go three we can do that that's fine and let's actually just send a bunch of requests here that have some different information so I'm just gonna say data equals that actually data equals a list and then inside of this list I'm just gonna fill up a bunch of different information here and we'll just make a bunch of videos that we can do some more interesting queries okay oops I wanted to go enter there just trying to get this list to be somewhat organized so that we can read this a bit easier okay so tab there we go and we'll just do three videos for now so likes there's no 78 name let's go Joe I mean name this really should be the name of the video let's just go how to make REST API views well this is gonna have a lot more likes hopefully and then we'll go views you know 80 thousand or something like that and then we can leave this Tim one the same but let's just make it a different amount of views let's make it two thousand let's give it 35 likes now what I'm gonna do is just send a bunch requests I'm gonna say for I in range I guess this is gonna be the Len of data what we'll say is and we'll just use all this okay so response equals request up put base video slash plus string I cuz this is gonna be whatever I is that'll be the ID we pass and then instead of that we're gonna go data I awesome will print me response dot JSON and at the very end here will actually go through and will delete one or two of them so we'll say response equals request get let's go base plus and instead of gets this is actually gonna be delete will go base plus video slash 0 I know that one will be there and then let's print out the response JSON so let's go print response dot JSON alright so what I'm doing is just sending a bunch of requests with different information that is stored in here me and delete one of them and I'm gonna try to get to video two and let's just see how that looks I'll add some inputs here okay so run I think this is refreshed yes the server's going now let's run tests up high and see what we get okay so first we got all these successfully and then something happened expecting value one a line column one I can't see exactly what that ah it's because I'm to do a response JSON from something that doesn't have any JSON data being attached to it so sorry about that guys essentially the reason that was that I just got that error there was because on this side I had dot JSON after my response but notice though when I have a request that is the delete method we don't actually return anything that's kind of a JSON serializable object we just return a blank string so that means we're not gonna be valid to be able to use dot JSON so we just have to use response so now let's try this one more time let's first just rerun this server just clear the memory there so python main dot pi and then we'll go python test dot pi notice this works fine let me hit enter we get response 204 that works fine and then named Tim views 2000 likes 35 when we query for ID I believe was 2 or 3 or something like that anyways you get the point that works successfully and our API is functioning pretty well so the next thing I'm going to show you how to do now is actually add this to a real database so rather than using just memory what like we're using right now in videos how can we actually get this to store in a persistent database we're just gonna use a flask SQL alchemy with a I believe it's a SQLite database so I'm gonna set a little bit of stuff up that'll be right back ok so now we're gonna add the database so to do that what we need to do is actually first install another module called flask SQL alchemy this just gives us a really nice interface to work with databases it's kind of similar to what Django uses as well and it's just a very popular way for databases inside of flask now if you installed using the requirements dot txt method she did pip install - our requirements txt you already have that installed if you didn't then you're gonna need to go back to your command prompt you need to type pip install flask - SQL alchemy like that I believe that's how you spell it so SQL alchemy yeah it should be correct so pip install flask SQL alchemy make sure that's installed in your system again that might be pip3 depending on what system you're on and once you have that we should be good to go and actually initializing this database so inside of our code we're going to say from flask SQL alchemy import SQL alchemy then we're gonna say DB stands for database equals SQL alchemy app so again same thing that we did with API here just wrapping app and then what we're gonna do before this actually is we're gonna make it config so we're going to say app dot config so we're changing the configuration settings we're gonna add this one here which is SQL alchemy like a box or you can spell it like that although in all capitals so alchemy and then underscore database underscore URI so essentially we're gonna define what we want the location of our database to be so where we want it to be and the way that works is we do SQLite colon three slashes like that and then the name of the database so we're gonna say database dot DB so essentially we're saying the configuration here we're gonna do sq up SQL alchemy database URI is equal to and then whatever the name of the database is now say you want it to save that within a folder inside of the path you're currently on you would do something like TMP slash database DB and that would store it in a temp folder assuming you had created one inside of your current directory this is known as a relative path which means it creates it based on the current path that it's in so when we say database dot DB we're just gonna make a database DB file in the same directory as our current script alright after that what we're gonna do is we're in type DB to create all now what this is gonna do is actually create the database now we only do this once so after we run this script this first time and it actually creates and initializes the database we're not going to what do you call it we're not going to do this ever again now the reason for that is because once we create the database we don't want to reinitialize it because if we do that we're gonna override the tables or the data we already have in there now the only thing is we don't want to do this until we've actually defined the models that we want to have in our database so what I'm gonna do here is I'm gonna start coding out a mall to store videos so I'm gonna say class video model this is gonna inherit from model which I'm gonna import up here with a capital so from ask sqlalchemy import model like that and then what actually sorry what am i saying don't import model what I'm gonna do in here is say DB dot model so my bad we're not importing anything up here we're just gonna use the DB that we created right here stands for database DB dot model now what we can do here is actually define all of the fields that we want to have inside of our video model so the first one that I'm going to do is have ID so I want to store some kind of ID in my video model that's obviously gonna be the ID of the video so I'm gonna say DB dot column like that and then inside of here I'm gonna say DB integer cuz that's gonna be an int value and we're gonna say primary key like that equals trick now I'm not going to be going through too much database related stuff but essentially a primary key means that this is a unique identifier so it means this ID will be different for every single video that we store in this database so what's something to keep in mind next I'm going to do is say name equals a DB column a column is just one column of information so inside of a database we have multiple columns for each model we have tables inside of those tables we have columns each row is an entry or one kind of object of that table if that makes any sense or of that you know model whatever you want to call it so here we'll say DB and this is gonna be DB string we're gonna put how many characters we want to potentially have in this string I think the max amount of characters for a YouTube video is a hundred so let's just go with a hundred and then we're gonna say unique note that's not true we'll say nullable equals false now the reason we do this is essentially to say that this field has to have some information we're never gonna have a youtube video that doesn't have some kind of name so if you make nillable equals true that means that you can insert something into this model that doesn't have a name but we want to always have a name Serena's saying nillable equals false the next thing we need after name is we need the views so this one's gonna be very similar to the false first columns we're gonna say views equals d b dot column this is gonna be a d b dot integer this is gonna be nullable equals false we're gonna copy this again for the likes so we'll say likes equals DB column DB not integer knowable equals false and finally we're just gonna define a wrapper method just so if we print this out we actually get something that's somewhat valid so define underscore underscore wrapper under scrander score we're gonna put a self and what we're gonna do is we're going to return an F string by the way this F string only works in 3.6 and above so if you're not in 3.6 and don't do what I'm doing here just try to come up with your own way for it I'm gonna say video and inside of here I'm gonna say name equals name I'm gonna say views equals views and I'm gonna say likes equals likes now this essentially whenever you have an F string and you put something inside of curly brackets it will just actually print the value out for that variable or for the expression inside of the curly braces so we'll get name equals and whatever the name is you use equals whatever the views is and we can pat this out just so that it's a little bit easier to read okay so this wrapper also just only happens when you decide to print the representation of this object or you decide to look at it internally or ever you gonna decide to do that this will just give you a string representation so we can actually see what all these videos look like okay so now that we have a video model we can go ahead and do D be create alright after we make this model and that will make a data base for us that has this model inside of it so what we're gonna do is go and we're gonna run our script here so I'm going to say Python main dot PI and there we go go ahead it creates that model for us and we should be good to go after that so after we've done that we're gonna make sure we delete DV dot create all because we don't want to do that a second time or that's gonna override the data in our database and that should be pretty much it now we have the database setup and created and we're ready to actually start working with it now to actually make a new object in the database is really easy what you do is just make a new instance of this class that has all of the valid things that we need and then simply just commit it to the session I believe I'll show you how we do that in just one second but I'm gonna start by removing some of this stuff so first of all I'm gonna remove videos like that I'm gonna remove this abort right here and we're gonna start changing some of this code now to actually work persistently with the database so the first thing we want to do is instead of having gets like this what we're gonna do instead of returning sorry videos video ID we're gonna have to query the database and return something that fits the query that we have so we'll say that the result is equal to in this case we're gonna go video model query dot get and then inside of here we're gonna say ID equals video ID so essentially we're gonna look for some you know model some row some video inside of this video model that has the ID equal to video ID and then we're going to return that to the user now here's where it gets a little bit tricky right if I want to return this result well this result is actually going to be an instance of this class now I know I'm going into databases and there's actually a lot to explain with flask SQL alchemy but essentially the way this works is that when you query this video model it's gonna give you instances of this video model that match whatever you put inside of here so I put ID equals video ID I'm gonna get any videos that have this ID and since I'm just doing get it's gonna return to me only one but it's gonna be an instance so how can I actually serialize that instance and return that so that my test script here that's looking for a response will actually be able to read that information well and this is where we use something called resource fields and marshal with now a resource field essentially is a way to define how an object should be serialized so what I'm gonna do here then I say resource underscore fields equals and what I'm gonna do is define what I want on these fields to be so I'm gonna say I D and then I'm gonna go : fields dot string like that and now I'm gonna go up to flask restful I'm gonna import fields and I'm gonna import a decorator called Marshall underscore with I'll define what these do in just a second but inside of fields dot string what I'm gonna do is get rid of these brackets and just leave it like that what I'm pretty much doing is I'm saying okay I want to make this dictionary here it's gonna define the fields from this video model that I want to return if I return a specific object seem confusing I have to keep coding for it to make more sense but just follow with me I'm trying to say that this ID field here which is the name that I'm putting here is equal to field stop string right like that's the type of field that it is next what I'm gonna do is I'm gonna say the name field which is another one that I want to look at I'm gonna say name is equal to fields dot strength and sorry ID should be fields dot integer my bad on that name is gonna be field string and then views and likes are gonna be the same thing they're gonna be fields dot integer field stunt integer and then we're gonna go likes it is fields dot integer awesome so now we have all of the fields defined we have our ID as well and we should be good to actually start using this so what we do when we actually want to take some object because result is gonna be an object when we have video model query that gives us an object of an instance video model so what I'm gonna do is of this I'm gonna say at Marshall width and inside of here I'm gonna put resource fields now what this says essentially is that when we return take this return value and serialize it using these fields so it's going to assume that we have an ID name views and likes on the instance that's returned it's gonna take those fields and it's going to essentially serialize it into this JSON format that can be returned so we'll create a dictionary that looks something like ID and then whatever the ID is there right and the name and whatever the name is there and views and likes and all that that's what this decorator is doing and you can put that above any method inside of here inside of your class that you want to return and have the object serialized with so let's try that now I'm gonna get rid of put actually we won't get rid of put we'll just modify this slightly so now inside of put what I'm gonna do is show you how we can actually make a new object in the database so to do this I'm gonna say let's go I don't know video equals video model and then inside of here we just need to define all the fields so we're gonna say ID equals video underscore ID name equals we're gonna need those args I'm gonna say args equals believe it was video put args dot parse args so we're going to say name equals args and inside here we're gonna put ID or not ID name and then it's after that we're going to save use equals args views and then we are going to say after views I believe that was likes equals args likes okay so this is a dictionary remember args that stores all of the values that we passed in we've seen that many times so I can access them individually like that and well I can just do this and that will create a new video model now if I actually want to make sure that that goes into the database so I'm actually committing it essentially what I'm gonna do is I'm gonna say DB dot session dot add video this is going to add this object to the current database session and then what I can do is I can say DB dot session dot commit and what this will do is commit any of the kind of changes I've made to the session and make them permanent in the database so right now when I say add I'm temporarily adding this video to the database when I say come I'm permanently putting it in then what I can do is I can return that object again so let's say return the video like that with a 201 but I need to make sure I add this marshal so that that gets serialized so Marshall with resource fields again that's because this is an object I can't just return an object back I need to turn something that's serializable and well this Marshall with will serialize this response and make sure I can actually return it fine now deletes same thing here we're gonna have to actually do something different to delete I'll do that after but let's just see if this is working I think this query might be a little bit off but anyways yeah let's deal with that so let's go to test let's get rid of this delete and let's see if the put actually works at all and then we can yes try to get something as well okay so let's give this a shot now not a hundred percent confident but we will give it a go okay so let's run this here and let's go python test op pi and that actually seemed to work so we see that these three happened it actually returned us the correct information we can see that that serialize ER is working if I hit enter here then we actually get an issue so get got an unexpected keyword argument ID okay so we had a small problem here in this query that's because this actually should be filter by my apologies so filter by video ID equals video ID but it's actually gonna be ID equals video ID and then dot first so what this is saying sorry is we're gonna filter all of the videos that we have by ID we're gonna look for the one that has the ID video ID and then we're gonna return the first response in that filter the first entry that's filtered by that the reason we do this is because I could technically filter say by views right I can say I get filtered by views equals and I could buy anything that has ten views and well there might be multiple videos that have ten views so I can get just the first one or I can get all of them I believe by doing dot all so let's do dot first and let's see how this works now and scope Python and what is the error here expect value line one column one chart zero I think something happened here let me have a quick look okay so you can see what actually happened there was that inside of our test script here we try to add things with IDs zero one two three now since those IDs actually already exist in the database we're getting an integrity error here it says unique constraint failed on ID and it's crashing our our server here now the way we can avoid something like that again is just making sure that ID doesn't exist so what I can say is we can check by querying the database or we can do like a try-catch to see if this worked or if it failed but let's just go ahead and say after args we'll set result equals video model query dot filter by ID equals video ID dot first okay so I just did a little testing on my own here to make sure I wasn't steering us in the wrong direction what I'm gonna do inside of here this might not be the best way to do this but it will work for our purposes is I'm gonna do a query and just check if there's any videos that have the ID that's equal to the video ID that we want to add if they do what I'm gonna do is abort so I'm just gonna say if results I'm so like if result exists then what I'm gonna do is say abort on abort with a 409 status code which means this already exists I'm gonna say message equals video ID taken dot dot dot so this way now we won't actually crash the program what we'll do is we'll simply send this abort message that says hey we already have this video ID you can't use that right so let's give this a shot and let's see what we get here if we try that so let's go and let's try this again okay so let's go python test stop hi and notice we get message video ID taken video ID taken video ID taken we can hit enter now and then we will get the video that corresponds with ID - so that is the basics there on how we can handle this put and just do a query and check if if this video exists and if it does we can just abort now same thing up here and get though I want to make sure that we actually get a valid result before we go ahead and return it so we're gonna say if not results so essentially if we don't get any results for the ID then what we'll do is we'll just abort will abort with a 404 and we'll just go message equals could not find video with that ID perfect that's all we need and let's go ahead and run this now after I change the test script and try to get a video that has idea say six so let's run this I'm gonna go back to my command prompt and video ID taken video ID taken message could not find video with that ID so that is pretty much it when it comes to actually saving things in a database and then handling some of these edge cases like oh the video already exists oh we can't find that video ID and so on now the next thing that we could do is do an update now I'm just gonna kind of leave this as something you guys can figure out on your own cuz I think with this knowledge you should be able to but you can define sorry what's called a patch so a patch is essentially a way to update so it's just that HTTP method for update I believe update is one as well there's a bunch of different HTTP methods or kind of yeah I think the methods that you can use but we're just patch is kind of the standard when it comes to actually updating something and what you could do is the same thing right so you can get all the arguments that you want to use to update a specific video and you can actually change this video put args to be something that doesn't have required arguments so say on an update maybe they can pass you just the video ID so if you go video ID like that and then any other arguments that they want to update the video with so maybe they just want to update the views well in that case it would be valid for them to just send you the updated views rather than sending you all the other things that they want all the other stuff they're not even gonna update right so they send you just views then what you could do is you could query the database you could get this object you can modify this object you can add it back in and you can commit and now that I say that you know let's just go ahead and do this because why not I'm gonna make another argument parser here I'm gonna say video updates args you fools I'm gonna say a request parse dot request parser we're gonna say video update args like that oops video not dot video update args dot add argument inside of here we're gonna add actually all the same arguments so I can literally just copy these and I'll just change the name so video update update and update and then here instead of required I'll just make all of these optional so this way now the user can send us whatever arguments I want so any of these three or all of these three and based on what they send we will update the video with them so this is gonna be a little interesting there's probably a better way to do this than what I'm about to attempt but I haven't done this before so I'm just going off the top of my head I'm gonna say args equals video underscore put underscore argh stop parse args we're gonna make sure that this video exists first of all so let's just say results equals video video model that query filter by ID video ID will do the same thing here so if result and it's actually in so if result will say if not results then will abort with a 404 and we'll say message video doesn't exist cannot update perfect that's all we need and then after that what we'll do down here is if we have a result will actually update that result so we'll say for argh in args and this is gonna be interesting to do cuz I kind of just need to check them manually I'm trying to think of as a better way to do this than what I'm gonna do but we'll have to see here okay so if this is gonna be a weird way but we'll just say if name in args then what we'll do is we'll say video model dot name equals args name now I think you guys are getting the point here of what I'm gonna just literally be doing the whole time I'm gonna say if views in args then we can say video model views equals args views this probably there's probably a way better way to do this in fact I kind of think of one off the top of my head but it's fine we just have three things here and we'll say if likes in args then we'll say video model dot likes equals args likes so essentially making it so that we can update everything here now what we'll do since we've updated this video model and why am i putting video model I'm sorry this should be result guys my apologies on that or any say results and results the reason I'm doing result is because I want to change this instance I don't want to just change the model itself so result that name result of use results dot likes and then what we'll do is we'll say DB dot session dot add results and we'll say DB dot session dot commit like that and then put our brackets and then we will return just the updated object so we're gonna return result like that and we could return it with a status but I don't know what the status is for updated so I'm just gonna leave that for right now now on patch we're gonna have to remember to add that Marshall with so Marshall with those resource fields and this should be good so let me test this out and make sure this is gonna work and then we will be good to go here so instead of get let's now do an update so we already know we have these three added in so we have ID zero one two let's just try to do an update here and see if we can get this to work so response dot patch like that we're gonna say base plus video two and here for our data we're just gonna pass views equals ninety nine not cool in ninety nine sorry and let's see when we get our response back if this actually worked properly or not so we're gonna run run let's run test op PI message name of video is required okay interesting so let me run that one more time name a video is required I believe I am using the wrong argument thing here so set of video put args we're gonna say video update arcs my bad about that guys let's go back and let's run this and what is the problem let's just have a quick look okay so I am back I did a little bit of a test there and some things were going wrong so I just figured out those areas I want to come back and talk to guys about what those were so before I had DB dot session dot add result right first of all we don't need to do that anymore because I realized I was just looking at some documentation that once it's already in the database we don't need to re-add it we can just commit any changes we make to the object but essentially the main problem that I'm having here is that we have this result object right and I say if name in args if you and args if likes and args then go result that like C was args result of use equals arc views so on so forth and we're updating the object like that which actually works but the problem is that name and views and likes are actually always in this argument even if what they weren't passed through that's because what this request parser does here is it actually will automatically fill these in with the value none if they are not passed through so what we need to do is first of all make sure that if we're gonna update that those values aren't snot so we're just gonna change these if statements say if name in args and arg is a name not none so we can actually just write if args a name and what that will do is tell us if this is if this key is not a none value and we don't have to worry about this giving us a key error because we know that we will always have args name args views and args like we know those will always be in that dictionary based on the way that the request parser works so I'm just gonna go change this here to say this now and we'll notice that this should hopefully be working when we go ahead and change this or when we run this now so we're just making sure that these values are not none if they're not none will update the result we'll commit those changes and then that should be good so let's go here looks like the server's automatically updated and now if I run Python tests up high we can see ID two named Tim views 99 likes 35 and if I go here and now I add say likes you know 101 let's see if that updates it so let's run test up again and there we go so you have views 99 likes 101 and just to prove to you that this will work even if I don't add anything Oh at zero data in there versus zero data no data and run this and it just stays the same as what it was before so that is how we use a data base that is how we update the information that's how we have the correct request parsers and everything else that I can think that you would really need to do if you're making some kind of API especially in flask so I think with that I'm gonna end the video here so this video is taking me a long time to create quite a few errors and things had to go through some code ad right beforehand you guys appreciate these this effort all I ask is that you leave a like on the video subscribe to the channel and maybe even leave a comment and let me know it really does keep me going and motivate to keep making videos so that being said if you enjoyed like I said like the video subscribe and I will see you guys in another YouTube video
Info
Channel: Tech With Tim
Views: 719,539
Rating: undefined out of 5
Keywords: tech with tim, rest api python, python rest api, python rest api tutorial, api rest tutorial, python rest api tutorial for beginners, flask rest api, flask rest api tutorial, flask rest api python, python flask rest api, python flask api, rest api tutorial, python rest api flask, rest api with flask and python, rest api with flask, rest api python tutorial, rest api, flask, python flask, rest api tutorial for beginners, build rest api python, flask python
Id: GMppyAPbLYk
Channel Id: undefined
Length: 74min 1sec (4441 seconds)
Published: Fri Jul 10 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.