Working with APIs using Flask, Flask-RESTPlus and Swagger UI | by Karan Bhanot | Towards Data Science

While working on Machine Learning projects, I decided that I would like to develop complete applications. This would require developing APIs, so that we can post values and get responses of predictions. This is where Flask and Flask-RESTPlus come into the picture.
Flask enables exposure of Python functions as APIs. Flask-RESTPlus is an extension to Flask which improves upon its capabilities. It allows us to not only define REST APIs but also brings in Swagger UI for all the APIs.
In this article, I’ll explain how I developed a Flask application with several APIs and dummy data. The project is available as a GitHub Repository.
I began the process by creating a virtual environment using pipenv. You can read more about it in my article on comparison of virtual environments. I installed Flask and Flask-RESTPlus.
pipenv install flaskpipenv install flask-restplus
However, if you do not wish to work inside a pipenv environment, you can simply use the following commands.
pip install flaskpip install flask-restplus
I began by importing Flask from flask. From flask_restplus, I imported Api to define the app and Resource which is received as a parameter in the various classes defined in the project.
I defined the application as a flask application using the method Flask() which sets the name using __name__. Next, I’ll used Api to initialise the application.
I defined a namespace here. The concept is very simple. Whenever APIs are defined under a given namespace, they appear under a given heading in Swagger (we’ll explore Swagger later in this article). In namespace, the first variable defines the path and second defines the description for that space.
In the example above, the url for the namespace is http://127.0.0.1:5000/main and has the description as Main APIs in Swagger.
Lastly, I defined the endpoints. As our namespace is name_space, I’ll define the url through route as @name_space.route("/"). Next, Flask-RESTPlus requires us to define all endpoints under a given route inside a class. The methods can beget(), put(), and many others.
In the example above, the APIs can be accessed at the path http://127.0.0.1:5000/main. The classname is set as MainClass with two methods, get() and post(). Whenever, I make a GET call, I get the reply with status field as Got new data and with POST call, I get the reply as Posted new data.
Now, everything is set up. The file is saved as basic.py. I run the app by the following command using pipenv.
pipenv shellFLASK_APP=basic.py flask run
Using pip, you can use the following command.
FLASK_APP=basic.py flask run
The best part of Flask-RESTPlus is that it automatically documents the APIs that we have created and they are visible in the Swagger UI. Go to http://127.0.0.1:5000/ and you can see all the APIs.
Both APIs are visible under the main namespace with the description Main APIs. We can try either API and check their functioning by clicking the Try it out button.
I used curl to make GET and POST requests from the terminal.
While using the curl command, first use the word curl followed by the method after the character -X. Finally, the endpoint is specified. Taking a look at our curl responses, we see that I received the correct data for both GET and POST APIs.
There is so much more to Flask and Flask REST-Plus. Let’s explore them in even more depth and understand them better. The following code is available as app.py in the GitHub Repository.
We can use a POST request to send data and save it. We can then use the GET request to get that data. Let’s say we have a project that manages names of individuals and stores them. We create a GET endpoint to fetch the name using id and POST endpoint to save a name against an id.
Here, I have created the path as http://127.0.0.1:5000/names/<int:id> where we will pass the id each time. To store names, I have created an object list_of_names which will be used to get and receive data.
We have already imported Flask, Api, and Resource. We also import request from the flask package. This helps us get the request object and then retrieve information such as JSON data from it. We also import fields from flask_restplus package to define the type of elements such as String.
We can also add extra information to our Flask app. This information is useful and is displayed in the Swagger UI.
We can define the version, title and the description of our application. We’ve set only one namespace namely names. The Swagger UI header would now look like the image below.
Whenever we want to receive or send information in a particular format (JSON) we accomplish this with the help of model. We specify the name of the model. Next, we describe the information it expects and the properties of each expected value.
We define the model name as Name Model. It includes one parameter, namely name which is a required field, and define its description and help text. The API which will use this model will expect a JSON with a key as name.
To keep track of all names, I’ll store them in list_of_names.
Let’s break down the code snippet above into smaller parts to understand it better. We’ll explore the POST endpoint. The functionality of GET would be very similar.
Define route and class
We use the name_space namespace to define the route i.e. http://127.0.0.1:5000/main/<int:id>. It expects an Id to be sent as an integer. The name of out class is MainClass which has one parameter, Resource.
Define docs for the API
Using doc we can define the documentation for the API in Swagger. The responses key defines the various possible HTTP Status Codes. For each status code, we also define a text that describes it to the user. The params key defines the expected parameter. The API expects id in the URL and we specify a help text for the user. The Swagger UI looks like the image below.
The parameters are defined in the top part. All the expected responses with their description appear in the lower part.
Define the method
We can now define our method. Before our method, we add the line expect(model) which defines that the API expects model. We wrap our code inside a try block and catch all errors that might occur. The request.json['name] gets us the received name and we can save it as well as send it back in the response. If the name key is missing, we get KeyError and we send Status Code 500. In other cases, we send Status Code 400.
Let’s start the app.
FLASK_APP=app.py flask run
POSTWe parse the response from the request, read the name and store it against the id in list_of_names. We also return the status and the name of the newly added person.
Error in POST Request
Say, we forgot to supply the name parameter in the data object. In this case, we’ll get an error.
On not supplying the key name, we got an error with Status Code 500 and the message Mapping key not found.
GETWe just pass the id that we want to get the name for and we get the status and the name of the person back if available.
Error in GET Request
Say, we don’t have any person against Id 2. If we try to retrieve that information, it’ll throw an error.
As that specific Id is not found, we get Status Code 500 and the message Mapping key not found.
In this article, we explored creation of APIs using Flask and Flask-RESTPlus. Both of these are great libraries to develop as well as document APIs in Python and interact with APIs using Swagger.
Please feel free to share your thoughts and ideas.