Srikanth Technologies

Creating REST API using FastAPI

Building REST API is one of the common requirements for many companies and it is made very simple using FastAPI framework and Python.

In this blog, I create REST API that allows clients to read, create and delete employee details in EMPLOYEES table.

Installing FastAPI

Install FastAPI and dependent components using the following PIP command:

pip install "fastapi[all]"
For more information, please visit https://fastapi.tiangolo.com/tutorial/

Hello World REST API

In order to create a simple Hello World REST API, we need to import FastAPI class from fastapi module and create an object FastAPI. Then create a function with decorator @app.get(path) that is associated with GET request and given path.  Value app in decorator is the object of FastAPI created before the function.

Whenever GET request is made using the given path then the function is called. Function name can be anything you want.

The following is the code in hello.py.

hello.py

from fastapi import FastAPI

app = FastAPI()

@app.get("/hello")
async def hello():
    return "Hello World"

In order make the above API available to clients, we need to run web server (uvicorn) provided by FastAPI as follows from the folder in which hello.py is present.

In the command app refers to object of type FastAPI created in hello.py.

Option --reload reloads changes made to hello.py without having to restart the server.

>uvicorn hello:app --reload
←[32mINFO←[0m:     Will watch for changes in these directories: ['c:\\dev\\python\\fastapidemo']
←[32mINFO←[0m:     Uvicorn running on ←[1mhttp://127.0.0.1:8000←[0m (Press CTRL+C to quit)
←[32mINFO←[0m:     Started reloader process [←[36m←[1m27104←[0m] using ←[36m←[1mwatchgod←[0m
←[32mINFO←[0m:     Started server process [←[36m8520←[0m]
←[32mINFO←[0m:     Waiting for application startup.
←[32mINFO←[0m:     Application startup complete.

Start browser and enter url - http://127.0.0.1:8000/hello to get message "Hello World".

Employee API

Now let's create a more complete API that allows GET, POST and DELETE requests from clients.

SQLite Database hr.db contains EMPLOYEES table and it is accessed using sqlite3 module.

We use EMPLOYEES table with following structure to store data. REST API internally uses EMPLOYEES table.

Use the following CREATE TABLE command to create table and insert some rows using INSERT command.

CREATE TABLE EMPLOYEES (
    Id       INTEGER      PRIMARY KEY AUTOINCREMENT,
    fullname VARCHAR (30) NOT NULL,
    job      VARCHAR (10),
    salary   INTEGER (10)
);

insert into employees(fullname,job,salary) values('Andy Roberts','SP',1500000)

It is possible to use any other database as long as you know how to access it.

employee.py

import sqlite3
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel

DBPATH = r"c:\dev\python\fastapidemo\hr.db"

# Model to represent employee 
class Employee(BaseModel): 
    name: str
    job: str
    salary: int

# Convert tuple containing employee details to dict 
def record_to_dict(emp):
    return {'id': emp[0], 'name': emp[1], 'job': emp[2], 'salary': emp[3]}


app = FastAPI()

# Handle GET request 
@app.get("/employees")
async def get_all_employees():
    with sqlite3.connect(DBPATH) as con:
        cur = con.cursor()
        cur.execute("select * from employees order by salary desc")  
        employees = []

        for emp in cur.fetchall():
            employees.append(record_to_dict(emp))  # Convert tuple to dict

        cur.close()
        return employees


#Handle POST request to insert row into table 
@app.post("/employees")
async def add_employee(value: Employee):
    with sqlite3.connect(DBPATH) as con:
        cur = con.cursor()
        try:
            cur.execute("insert into employees(fullname,job,salary) values(?,?,?)",
                        (value.name, value.job, value.salary))
            con.commit()  # make insertion permanent
            return value
        except sqlite3.DatabaseError as ex:
            print("Insertion Error : ", ex)
            raise HTTPException(status_code=500, detail=str(ex))

        cur.close()
        con.close()


# Handle DELETE request to delete row 
@app.delete("/employees/{id}")
async def delete_employee(id: int):
    with sqlite3.connect(DBPATH) as con:
        try:
            cur = con.cursor()
            cur.execute("delete from employees where id = ?", (id,))
            if cur.rowcount == 1:
                con.commit()    # make delete permanent
                return None
            else:
                raise HTTPException(status_code=404, detail="Id not found")
        except sqlite3.DatabaseError as ex:
            print("Deletion Error : ", ex)
            raise HTTPException(status_code=500, detail=str(ex))
Run Employee API as follows:

>uvicorn employee:app --reload

Note: You can get documentation (Swagger UI) regarding API by using /docs or Redocly using /redoc.

Consuming Employee API

In order to consume Employee API, we use Postman application, which allows us to make GET, POST and DELETE requests for the given URL.

Making GET Request

Select GET from methods and enter URL as shown in the image below:

Making POST Request

Select POST from methods and provide data to be sent to API in JSON format as shown below. Upon successful insertion, API sends data back to client.

Making DELETE Request

Select DELETE from methods and send employee id along with URL as shown below. If you send an ID that is not existing then API returns 404 as response.

All the best!