Build Python web APIs using FastAPI
Tags: python, api, fastapi
Published: 2022-10-02 12:12:23

Application programming interface is an important component that makes your application accessible to a wide range of users. Nowadays, it is not a difficult task to create API however, it might be challenging to choose the right framework.

Python is well known for its ability to implement various AI, ML, DL tasks. It has some micro frameworks such as flask and Django for building web APIs. Nowadays, developers are switching to a much younger framework, FastAPI.

In this section, we will learn the basics of FastAPI.

## Getting Started

### What is FastAPI
FastAPI is a modern, high-performance, web framework supported by Python 3.7+ versions. It was released in 2018 as an open-source framework based on standard Python-type hints. It is built on the Asynchronous Server Gateway Interface (ASGI) web server Uvicorn, which also mounts Web Server Gateway Interface (WSGI) applications.

Key features

- **High speed**— FastAPI is a high-performance Python web framework because of ASGI, which supports concurrency and asynchronous code by declaring the endpoints.
- **Built-in concurrency** — FastAPI eliminates the need for an event loop or async/await management. The initial path function can then be specified as coroutines using async def and await specific locations.
- **Dependency injection support** — FastAPI supports a dependency injection, which makes it easier to make changes to your code. It increases the modularity of the code and the scalability of the system.
- **Built-in docs** — FastAPI provides automatic interactive documentation which simplifies the use of the backend by front-end engineers, and simplifies API endpoint testing.
- **Built-in validation** — FastAPI built-in validation detects incorrect data types and returns the underlying reasoning in JSON. It uses the Pydantic module to simplify validation.
- **Standards-based** — Based on the open standards for APIs: OpenAPI and JSON Schema.

### Flask vs FastAPI
Flask is a micro python web framework used for building lightweight web applications. It is built on the Werkzeug toolkit and Jinja2 templating engine and is deployed on WSGI (Python Web Server Gateway Interface).

FastAPI is a modern and high-performance web framework used for developing APIs supported by Python 3.7+ versions.

Flask is an aged popular micro web framework suitable for lightweight applications whereas FastAPI is a full stack framework used to build solutions with rich documentation, and validation. FastAPI supports concurrency and makes it much faster than flask.

> Flask is better for simple microservices with a few API endpoints whereas FastAPI is preferred for speed and performance.

![Flask vs FastAPI](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sd8hw1tois535c4nrjvl.PNG)

### Setting up the Project
We can setup the fastapi project through the usual Python project setup steps.

- Create a folder for the project and navigate to it.
```
mkdir firstapp
cd firstapp
```
- Create a virtual environment and activate the same.
```
python -m venv venv
venv/Scripts/activate
```
- Install FastAPI and uvicorn, an ASGI server:
```
pip install fastapi uvicorn
```
![Install dependencies](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/21fpjrvlzhtgem0hbsyt.PNG)
### FastAPI Hello World
Let’s try to create the traditional “Hello World” app up and running in FastAPI. It will help you to understand the initial setup of the app.

- Create a file main.py and add the following code to it.
```
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
async def root():
    return {"message": "Hello World"}
```
**Understand the code:**

- `Import FastAPI from fastapi package` Create an instance of the `FastAPI()` and assign it to the app variable
- `@app.get(“/”)` is used to execute the following method when the user requests the `/` path
- `async def root()`: runs the `root()` method as python coroutine
`return {“message”: “Hello World”}` sends it to the frontend

### Run the app
Execute the following command to run the app
```
uvicorn main:app --reload
```
The command uvicorn main:app refers to:
- `main`: the file main.py
- `app`: the object created with the line app = FastAPI()
- `--reload`: restarts the server after code modifications
You will get a URL in the console if the app is up and running. Open the URL in the web browser to see the API response.

![output](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3tvdyw4qba25souy6q2a.PNG)
![output](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/o5ky928sbcg205ctfvqf.PNG)

### Interactive API Documentation
FastAPI automatically generates fully interactive API documentation of your project. You can check it by hitting the URL `http://127.0.0.1:8000/docs` in your browser.
![docs](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z1iarw3xlfrwri2mrhmm.PNG)
You can check out the documentation using `redoc`(open the URL `http://127.0.0.1:8000/redoc`).
![redoc](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ao29p1g5bvw657qas3a9.PNG)
### Basic FastAPI building blocks
Let’s explore some of the building blocks of FastAPI such as path parameters, query parameters, and request bodies.

#### Path parameters
Path parameters are enclosed in curly brackets {} which helps in scoping the API call down to a single resource.

```
from fastapi import FastAPI
app = FastAPI()
@app.get("/user/{name}")
async def read_name(name):
    return {"user name": name}
```
The value of the path parameter name will be passed to the function `read_name()` as the argument name.

![output](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/isqbdoyst2k38cvlsrdx.PNG)

#### Query parameters
The function parameters that are not a part of the path parameters are automatically interpreted as query parameters. They start with a question mark `?` in the URL string.

```
from fastapi import FastAPI
import random
app = FastAPI()
@app.get("/user/")
async def create_user_id(start: int, end: int):
    return {"user id": random.randint(start,end)}
```
The query is the set of key-value pairs that comes after the question mark `?` in the URL, separated by an ampersand &. Open the URL `http://127.0.0.1:8000/user/?start=1&end=10` to see the result.

![output](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/18c2upc1farrzlkf3e3m.PNG)

#### Request body
We can also send data to the server in the request body. Use Pydantic models to format the data which we receive from the request body.

```
from fastapi import FastAPI
from typing import Optional
from pydantic import BaseModel
class User(BaseModel):
    name: str
    age: Optional[int] = None
    gender: str
    phone: Optional[str] = None
app = FastAPI()
@app.post("/user/")
async def create_user(user: User):
    return user
```
You can check the user post API (`“/user”`) using the FastAPI doc tryout option. For which, open the URL `http://127.0.0.1:8000/docs`. Select the create user post API and click the Try it out button. Provide the user information in the request body and hit the execute button. You can see the response in the response body if the request was successful.

Also, you can try the post API using postman.

![request body](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0hxocs8kvyvkbjhipwme.PNG)
![request body](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/p0cn2f6f8osdghwxxy44.PNG)
![request body](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8h5b51y0a2zrzit1br2l.PNG)

#### Data conversion
Declaring the type of a path parameter will give you support for error checks, data conversion, and so on. FastAPI does automatic request parsing if you mention the type of the parameter.

```
from fastapi import FastAPI
app = FastAPI()
@app.get("/user/id/{id}")
async def read_name(id: int):
    return {"user id": id}
```
![output](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bfjbghcv2uuoejrl22q3.PNG)
Notice that the value returned is 5, which is int and not string "5".

#### Data Validation
FastAPI also gives you built-in data validation support and provides you the error messages if any validation error occurs.

```
from fastapi import FastAPI
app = FastAPI()
@app.get("/user/id/{id}")
async def read_name(id: int):
    return {"user id": id}
```
If you hit the URL `http://127.0.0.1:8000/user/id/foo` then you will get an error message “value is not a valid integer” due to the type mismatch.

![output](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wfp9qt1dtbulwd7xblo7.PNG)

Thanks for reading this article.

Thanks Gowri M Bhatt for reviewing the content.

If you enjoyed this article, please click on the heart button ♥ and share to help others find it!

The article is also available on [Medium](https://blog.devgenius.io/build-python-web-apis-using-fastapi-7f1524139428).

The full source code for this tutorial can be found here,

[GitHub - codemaker2015/fastapi-examples: two fastapi example projects](https://github.com/codemaker2015/fastapi-examples)

Useful links,

- [FastAPI | fastapi.tiangolo.com](https://fastapi.tiangolo.com/)
- [GitHub - ChristopherGS/ultimate-fastapi-tutorial: The Ultimate FastAPI Tutorial](https://github.com/ChristopherGS/ultimate-fastapi-tutorial)