[Part 2] RESTful API’s using Flask: HTTP verbs, statelessness & the REST paradigm.

Umar Khan
Analytics Vidhya
Published in
7 min readApr 1, 2021

--

Let’s take a step back and revisit how the internet works.

When you type “www.facebook.com” into your browser, it reaches out over the internet to a server. A server is program running on a dedicated computer that can respond to browser requests and deliver content to the user. These requests and responses are transmitted using the HyperText Transfer Protocol (HTTP), which is really just a standardized way for computers to exchange data over the internet.

HTTP defines methods (also called HTTP verbs) that are used by browsers and programs to make requests received by and acted on by servers. These include GET, POST, PUT, DELETE and others. GET is the most commonly used verb. When you point your browser to a URL, it sends a GET request to the server thats registered to receive requests to that URL. The GET request tells to server to deliver the data (web page with text pictures and other content) for that URL. When you go to facebook.com, your browser sends a GET request to the Facebook server to the endpoint associated with the base URL. The server has been told to deliver the login page when a request is sent to that endpoint, and that is what you see.

API’s then utilize these same HTTP verbs to receive requests from users and deliver data in responses or modify it’s stores of data. In our last post we added a get method to our resource class to let the server know how to handle GET requests sent by the user towards an endpoint on our server. We can similarly use our API to add data to our server or delete it. We just have to write out our endpoints, the resources associated with those endpoints, what kind of requests the resources an handle and how they will end up handling them.

What makes an API a REST api is it’s adherence to certain principles and conventions that are the core of the REST paradigm. REST conceives of APIs as a set of resources that can be interreacted with, to either retrieve or modify data. We saw this in our app, where we created a resource object, associated it with our endpoint and added the resource to the flask_restful. When the app is deployed, calls to the endpoint will be received by the server, which will refer it to flask_restful, which will pull up the resource for the specified endpoint and run whatever code is in it to generate the correct response.

Another key aspect of this is that a REST API should be stateless (REST stands for REpresentational State Transfer). State is an entire field of study in CS, and it’s hard to get into it. Essentially what statelessness means in the context of REST is that the response a server makes to a request should not depend on any previous request. What this boils down to is separating the data storage from the handling and delivery and having our API serve as a gateway to a database.

We left off the previous post having a functioning API running on our local server. However the records of this API, being a simple python list defined in the running script, were stored in short term memory (RAM). Variables declared in scripts in this way only exist while the script is running and are lost if the program terminates. Furthermore, RAM memory is limited and not meant to hold large amounts of information that’s not actively being used.

But most importantly, it violates the “statelessness” condition. Let’s say I have an endpoint in my API that returns a list of all the records in a location and another endpoint that allows me to add to this list. If I am storing all these in memory as in my sample script, than the list of all records will depend on the POST requests previously sent it.

So we have to store the data used by our API somewhere on a disk. The preferred method of storing data for retrieval is in a database. Everytime a user submits a request to our API, it will either retrieve data from or add data to our database. SQL is a standard choice, although JSON based NO-SQL platforms like Mongo-DB have become increasingly popular. In this tutorial, we will set up a SQLite database and have our API use it to send back requested data to the user.

There are a number of advantages to adding an API layer between our datastores and end users who may want to consume our data and services. It’s safer for one thing, having such an intermediary to your database. It presents a clean, unified interface with which its easy for any number of programs to interact with. Its modular, in that we can house alot of functionality in the API instead of the client side application, so we can make changes in one place and the consuming applications can continue to operate as usual since they are getting the outputs from the API they expect.

So lets set up a SQLite database to work with our API. In your root folder, create a new python file (call it ‘db_setup.py’ if you want). This is what this file will look like:

Lets walk through this. We import sqlite3, which is built into python so we dont need to install anything. The first step in working with SQLite involves setting up our connection object; this is how our Pyython script connects to our database. We specify the path and name of the database file here, and if we enter a filename that does not exist sqlite3 will actually create a database file with that name at that location.

Then we capture the cursor from our connection object. This object is what’s used to submit queries to our DB and it stores the results returned from submitted queries. Now we can simply go ahead and write SQL expressions and pass them into the execute method of our cursor object.

In the example above, we wrote out a query to create a table in our database and added columns to it. The tuple after animals contains the name of the columns we want in our table along with the type of data to be stored there. We then simply pass this to the execute method and this will create a table. And lastly make sure to call the commit method on the connection object to actually save your changes to the database, and close the connection also.

Here’s how we add records to the database:

After connecting to the database and instantaiting a cursor, we first defined a tuple containing the values we want for our record. Remember we made three columns, the first having integeres, the second two text. To insert this record into the DB we craft our query as shown above. Then we pass the query and the tuple with the actual record into execute and it knows to replace the “?” sequentially with the values of the tuple.

Okay so we know how to get data into our database. It’s easy enough to see how we can know retrieve data from the database using our API. We simply add the retrieval code to the resource associated with the endpoint and that’s it!

Notice how we again instantiate a connection, a cursor and pass a query into the cursor like we did before. Only this time, we wrote a select query, passed in the variable that the user passed into our endpoint and then retrieved the results from that query.

One thing I wanted to note. Take a closer look at this line:

Notice how when we passed in the name variable to the cursor. Seems odd to pass in a tuple with just one value. Unfortunately, this is just a quirk of SQlite: it demands that variables be passed in as tuples even if theres only one. After that, we capture the results from executing the query into “row” by calling fetchone on the result. Fetchone will return just one record and is usefull if we only want to get one record. This gets a list. If a record is found in the database matching what the user entered, we return that record in a JSON format by slicing out the list. If it is’nt found, we return an error message.

Not hard at all, right? Go forth and build!

--

--

Umar Khan
Analytics Vidhya

Just an attorney who wandered into data science and never wanted to leave.