Build API’s fast using FastAPI and Python

A basic python web app tutorial using FastAPI

Priyav K Kaneria
Python in Plain English

--

Introduction

Making APIs is not as hard as you think. You don’t believe me?!🤔 Try making a web app yourselves using this tutorial. This tutorial assumes that you have basic understanding and knowledge of Python language.

For complete newbies, I would first of all explain in noob terms, exactly what are APIs. They are basically, a pipeline connecting the user to the data where you have complete control over the dimensions, flow, filters and the start and end.

And FastAPI is one of the many popular web frameworks of python used by professional software developers for making web apps easily. It provides a backbone to the app due it’s speed, efficiency and easy-to-use-and-understand nature. It is based on Starlette and ASGI which are essential for the speed of FastAPI.

We are going to make a simple ✔ todo list application in this tutorial which will cover all basics of starting a FastAPI application from scratch. The application will include routing, storing data, reading the data and showcasing it in template and adding and deleting todo tasks.

First Steps

So let’s get started! We will first make a new directory named mytodo and create a virtual environment for this project to make sure the libraries do not conflict with other projects. We will name the env as todoenv and install FastAPI and Uvicorn.

If virtualenv is not installed you can do the same using:

For windows users : pip install virtualenv
For linux users :
sudo pip install virtualenv

For windows users:

mkdir mytodo
cd mytodo
virtualenv todoenv
todoenv\Scripts\activate.bat
pip install fastapi uvicorn jinja2 python-multipart

For linux users:

mkdir mytodo
cd mytodo
python3 virtualenv todoenv
source todoenv/bin/activate
sudo pip install fastapi uvicorn jinja2 python-multipart

Fast-api comes with fastapi-sqlalchemy and pydantic when trying to install. If it doesn’t, try installing them individually via pip

FastAPI doesn’t have it’s server like Django and Flask, so Uvicorn is an ASGI server which will be used for production and serving of a FastAPI

Building our first API

Now comes the part to make our basic API route and run it, using uvicorn. First build the code, run it and then we will see what exactly is happening BTS.

👀NOTE: If you are not using VSCode, I have only one thing to say…. use it!

We will start by running code . in the same terminal so it opens VSCode for us😎.

Make a new file named main.py in the mytodo folder. (Do not touch the todoenv folder !!) and write the below code in it.

Make sure you are using your environment that you made in VSCode by opening any Python file and clicking on the Ppython version name at bottom left corner and making sure it is Python 3.x.x 64-bit ('todoenv') . If it is not then set it as default python application by clicking on correct option.

from fastapi import FastAPI
app = FastAPI()
@app.get("/")
async def root():
return {"message": "Hello World"}

Come back to the terminal and run :

uvicorn main:app --reload

Wait until it says INFO: Application startup completeand then open “http://localhost:8000/” on any browser. You should see

{“message”:”Hello World”}

Congratulations! You have successfully made an API!

Explanation

So in the main.py we have first imported the required FastAPI() function and used it to declare the app.

Then, we use a decorator to define the routing of the root function. In the decorator, the important bits are the function get() and the parameter passed in the same. Here, get refers to the type of request the url should accept to run the function and the parameter in the function is the url itself.

A “/” url also means that even if nothing is typed after localhost:8000, still the function will run i.e. “/” is an optional url if nothing is typed after it.

Done with the first part ✨🤩

Making the homepage

Enough of basic stuff!

You might recall, we installed something by the name of jinja2 during pip installs. It is a template engine used for many tasks related to templates. We are now going to use it for rendering our templates. But, let us make the templates first.

In mytodo/templates/todolist.html write the following code -

In main.py make changes according to the following code -

Make a new file database.json to store the todo list that we make. Add this sample code to the json file -

Now run the code ( or just refresh the browser if server is still running )
And lo and behold🎉… we have a working todo list ready!

Your call: Try adding and deleting tasks and checkout the json file in between to get some idea about the process. The list by default should look something like this -

The working directory of the project should look like this for the project to work correctly -

Understanding the code

Now the time has come to understand the code line by line.

Let us start with main.py-

First of all, line 1 to 4 says that

from fastapi import FastAPI, Request
from fastapi.responses import RedirectResponse
from fastapi.templating import Jinja2Templates
import json

we have imported the required functions from fastapi and imported json. The RedirectResponse function will help us redirect to the main-page after going to add or delete API. The Jinja2Templates will be useful for using templates while parsing data and variables in templates. We are also using json library to store and read data from a json file which we will use as a database to store our To-do’s.

Next, we can see that we have defined a templates variable by providing a valid templates directory for us to directly use the templates in it.

After that, we have the below code snippet

@app.get("/")
async def root(request: Request):
with open('database.json') as f:
data = json.load(f)
return templates.TemplateResponse("todolist.html",
"request":request,"tododict":data})

Here we open our database.json and read it’s content using the loads function from json library. The data is passed to the template using the dictionary object in the TemplateResponse function. This function renders the template for us, whose name we provide as first parameter and parses the variables, we pass as dictionary object in the template.

It is necessary to provide the request variable to the template for rendering.

Let us now jump to the todolist.html template and understand it first before moving on in main.py.

{% for id in tododict %}
<tr>
<td>{{ tododict[id] }}</td>
<td><a href="/delete/{{ id }}"><button>Delete</button></a></td>
</tr>
{% endfor %}

This is the most confusing/interesting/important part. Here, we are using template formatting to use the variables that were passed and also using Python inside our template. The for loop, loops over the to-do’s and using
{{ variable_name }} as a format we are making a new row for every todo and also making a button along with the todo specifically hyperlinked to the “/delete/( id of the todo )” which we have defined in main.py for deleting the todo. The {% endfor %} provides the template a limit from where to where it has to repeat in for. You will also find the form to add the todo hyperlinked to “/add” to add a new todo.

Coming back to main.py, we can now understand the later defined delete and add API’s.

In delete API, one new thing we can see is, the way in which the api is defined.
It is defined as “/delete/{id}”. Here the curly brackets signify that any variable data can be passed as a API route where the id will be passed as the parameter of the API function.

We are again reading the current database and deleting the specific todo. But importantly we then need to update the database with the latest data which we can do by opening the file in write mode this time (denoted as ‘w’ )and dumping the json in the file.

We are then simply redirecting the user to our mainpage using our imported RedirectResponse function where we pass the redirect_url as “/” and the status code as 303 for temporary redirect.

Alas! The add API is quite easy to understand😁. After reading the data, we are getting the form that was posted from the html by awaiting the request.
Then, we give proper id’s to each task to make sure, we add todo correctly and THEN add our new task. The request provides us formdata type object which is a dictionary, with keys corresponding to the names of the inputs in the form.
The only step left is to update our database and we are done. (After redirecting !😅)

You can also go to http://localhost:8000/docs (while the server is running) and checkout the API’s we made in Swagger UI.

So this is how to make a fast API fast, using FastAPI!

You can get the repo here and comment below for any queries.

Thanks for reading, more on the way😇…

Also big thanks to Sebastián Ramírez for making FastAPI👌

--

--