Building REST APIs using Flask

Prakhar S
8 min readNov 25, 2021

--

Photo by Julian Hochgesang on Unsplash

Flask is a lightweight and fast python module for making for making web-apps as well as standalone APIs.

APIs , or Application Programming Interfaces can be thought of as a contract between and information provider and information user . Basically it allows two software applications, which could be written in different programming languages to talk to each other and share information.

REST API : REST stands for Representational State Transfer. APIs whose design conforms to the design principles of REST are known as REST APIs. For more information about these design principles , checkout this link.

REST has become the defacto way of designing APIs now, as the bandwidth requirements for information sharing is quite low for REST APIs compared to traditional methods and it allows for different data format such as JSON, XML, plaintext, HTML etc.

We will design a simple REST API for fetching and updating a movies data stored as a list within the app file itself, with the following endpoints for :

  • getting the names of all the movies in the list
  • adding a new movie to the list
  • getting the details of a single movie from the list
  • getting the list of the actors in a movie
  • adding an actor to a movie in the list

These are standard CRUD(Create, Read, Update, Delete) operations and we will be using the HTTP ‘GET’ and ‘POST’ methods for executing these endpoints

Lets get started by setting up an virtual environment and installing Flask

Create a folder on the desktop or any other location .

mkdir flask_api_project

Change the directory to go within the folder

cd flask_api_project

Install ‘pipenv’ which is a tool for managing dependencies and also creates a virtual environment within which we can work independently without worrying about any conflicts with other packages or the lack of them in our local system

 pip3 install pipenv

Once installed , activate ‘pipenv’ by running

pipenv shell

Now in the terminal , we should see the virtual environment being activated with something like this :

Also within the main folder there should be a ‘pipfile’ created which will contain a list of all the dependencies required for the project.

Now lets install flask by running

pip3 install flask

Once successfully installed , we are ready to go and create our flask api.

In the main folder , create an app.py file using

touch app.py

This is the only file that we will need for this project. Open app.py in Visual Studio or whichever IDE you prefer and write the following lines of code:

from flask import Flask, jsonify, requestapp = Flask(__name__)

‘jsonify’ serializes data to json format, since this is what our api will return, and the ‘request’ object in Flask contains all the incoming data from the requests made to the api. In the second line we create an instance of our Flask class for our api.

Now all we need is to add endpoints for the tasks given above. But before that lets create a ‘movies’ list , which will store the values we need to return or update using these endpoints. I do that simply by adding this list to app.py

The list contains 2 movies , each within a dictionary, having keys like ‘name’, ‘actors’, and ‘ratings’ . Actors for each movie is also a list of dictionaries, each dictionary having ‘name’ and ‘age’ as keys.

Get movies endpoint

Now lets start defining the endpoints for our api. The first one and the most simplest is to get all the movies in the list :

@app.route('/movies')
def get_movies():
return jsonify({'movies' : movies})

app.route here acts as a decorator to the function ‘get_movies’ , so that the function ‘get_movies’ is registered for the route ‘/movies’. Whenever this route or endpoint is called , the function ‘get_movies’ is executed and a json object of the form {‘movies’ : movies } is returned. The first ‘movies’ here is just the key name, and the second movies refers to ‘movies’ variable (list) created above. By default , if not method is explicitly given for and endpoint, ‘GET’ is taken to be the default method. So we have now created a simple api endpoint to get the list of the movies and it is ready to be tested.

Just add the following lines at the bottom of the app.py

app.run()

So now our app.py looks like this:

Now from the terminal run the following command as shown below:

We should get an output saying that the server is running on http://127.0.0.1:5000 or something similar which is just the address of our localhost running at port 5000. Copy paste the URL in the browser and add ‘/movies’ to the end of the url since that is the route which has been defined in our app, and we should get something like this :

If you are able to get the above output, well done ! You have just created your first REST API using Flask.

But right now our API only has one endpoint , serving a GET request. We will now create some other endpoints as well, as we mentioned at the start of the article . Let’s go back to our app.py file and start adding these.

Get a single movie by name

Add another route as below:

@app.route('/movies/<string:name>')
def get_movie(name):
for movie in movies:
if movie['name'] == name:
return jsonify(movie)
return jsonify({'message':'Movie not found'})

Here we define another route as before , only this time the name of the movie we want to fetch is passed as a string variable ‘name’ at the end of our route. This name is further passed as a parameter to our ‘get_movie’ function. Inside the function, the ‘for loop’ iterates over all the movies in our ‘movies list and if the name of a movie in the list matches the name passed in our endpoint, the movie is returned as a json object . If at the end of the ‘for loop’ the movie is still not found, and error message is returned. Note that a Python function can only execute one return statement when the function is called .

Get actors in a movie

Route for getting actors list in a movie

@app.route('/movies/<string:name>/actors')
def get_actor_in_movie(name):
for movie in movies:
if movie['name'] == name:
return jsonify({"actors": movie['actors']})
return jsonify({'message': 'Movie not found'})

Here we again pass the name of the movie as a variable , but also add ‘/actors’ in the endpoint to get actors list. We again iterate over the movies list and if we find the movie , we return the “movie[‘actors’]” for that movie. If the movie does not exist, we return the error message as before.

Create a new movie (POST)

Till now we have defined only the ‘GET’ methods, which are methods to fetch some information from the api. But we also have other methods we can use with our REST API such as ‘POST’, ‘PUT’ and ‘DELETE’. The ‘POST’ method is used for updating or adding information , which is what we are going to do next .

Add this route

@app.route('/movies',methods = ['POST'])
def create_movies():
request_data = request.get_json()
new_movie = {
'name' = request_data['name'],
'actors' = request_data['actors'],
'ratings' = request_data['ratings']
}
movies.append(new_movie)
return jsonify(new_movie)

Here the endpoint ‘/movies’ is the same as the endpoint for get_movies route, but we have explicitly defined the method to be post . Which means the function ‘create_movies’ will only be called when we make a ‘POST’ HTTP request. Note that we need to explicitly include the name of the metohd in the route if it is anything other than ‘GET’.

The function ‘ create_movies’ will first use the Flask’s request class to the get the request from the end user in a json form and store it in a variable called request_data. Then it will parse this json into a dictionary of key-value pairs, as that is how each movie is stored in our original movies list. Finally the parsed value will be appended to our movies list. The newly added movie is also returned at the end to indicate that the POST request was successful.

Add actor to a movie

This last endpoint will add an actor to a movie whose name is specified in the endpoint. Add this route to app.py

@app.route('/movies/<string:name>/actors',methods=['POST'])
def add_actor_to_movie(name):
request_data = request.get_json()
new_actor = {
'name': request_data['name'], '
'age': request_data['age']
}
for movie in movies :
if movie['name'] == name:
movie['actors'].append(new_actor)
return jsonify(movie)
return jsonify({'message' : 'Movie does not exist'})

In this route , the name of the movie to which actor is to be appended is passed as name variable in the endpoint. When the ‘add_actor_to_movie’ is invoked , it first gets the request as json data and parses it into ‘new_actor’ variable . Then it searches for the movie name in the list and adds the actor to the movie if it finds it else returns an error message as shown.

Thats it , our REST API is ready , and is able to handle both POST and GET requests. The GET request endpoints defined above can easily be tested using our browser , as already demonstrated for the first route we defined. But for testing the POST requests, we either need to add a HTML page to our flask app with javascript , which will call these endpoints or we can do it using a tool called PostMan. Since we are designing only a API and not a web-app with both frontend and backend, we will use Postman. This is quite simple and easy to do , but since this post is already too long , I will cover it in my next post, coming soon.

The complete code for this api can be found here.

Thanks for reading . Your comments or suggestions are welcome. Subscribe or clap if this was helpful .

}]

--

--