How to create a routing process with FastAPI

overview

FastAPI provides a facility to easily define routing. Routing is defined by specifying endpoints for handling HTTP requests.

Below, we’ll explore routing concepts, defining routes, creating route handlers, handling routing parameters, and options for routes in more detail.

Here, we will explain the routing method using the following versions.

FastAPI v0.68.1
Python v3.9.1

In addition, all the code created this time is posted on GitHub.

Routing concepts

Routing defines how a FastAPI application handles requests from clients when they reach a particular endpoint.

Routing is defined by a combination of HTTP methods (GET, POST, PUT, DELETE, etc.) and paths (URLs).

How to create a routing process

FastAPI uses decorators to define routing.

@app.<HTTP method>('<path>')
async def <function name>(<argument>):
  # handling routes
  • HTTP method: Specify the HTTP request method (eg get, post, put, delete, etc.).
  • Path: Specifies the URL path that requests from clients will match.
  • <function name>: defines the function that handles the route.
  • <argument>: defines the function arguments, if necessary. This includes path parameters, query parameters, request bodies, etc.

Specific code examples are shown below.

How to create various API methods

main.py

from fastapi import FastAPI
from pydantic import BaseModel
from typing import Optional

app = FastAPI()

class User(BaseModel):
    name: str
    uses: Optional[int] = 0

# Temporary data holding user information
users = [
    {"id": 1, "name": "John Doe", "uses": 5},
    {"id": 2, "name": "Jane Doe", "uses": 3},
    {"id": 3, "name": "Jim Doe", "uses": 7},
]

@app.get("/users/{user_id}")
async def read_user(user_id: int):
    # Acquiring user information, etc...
    for users in users:
        if user["id"] == user_id:
            return user
    return {"message": "User not found"}

@app.get("/users")
async def read_users():
    return users

@app.post("/users")
async def create_user(user: User):
    # User creation, etc...
    users.append({"id": len(users) + 1, "name": user.name, "uses": user.uses})
    return users[-1]

@app.put("/users/{user_id}")
async def update_user(user_id: int, user: User):
    # User updates, etc...
    for u in users:
        if u["id"] == user_id:
            u["name"] = user.name
            u["uses"] = user.uses
            return u
    return {"message": "User not found"}

@app.delete("/users/{user_id}")
async def delete_user(user_id: int):
    # User deletion, etc...
    for u in users:
        if u["id"] == user_id:
            users.remove(u)
            return {"message": f"User {user_id} has been deleted."}
    return {"message": "User not found"}

Commentary

  • Import required libraries:
from fastapi import FastAPI
from pydantic import BaseModel
from typing import Optional

FastAPI is the main class for creating APIs. BaseModel is part of the Pydantic library, responsible for input data validation, serialization and documentation generation. Optional is part of a type hint that indicates that a value is optional (can be None).

  • Instantiate FastAPI application:
app = FastAPI()

app creates a new instance of this FastAPI application. This is the main entry point for your application, where you configure things like routing definitions.

  • Defining the User model:
class User(BaseModel):
    name: str
    uses: Optional[int] = 0

The User class inherits from Pydantics BaseModel. This allows for data validation and serialization features. Here we define two fields, nameanduses`.

  • Define a temporary data structure to hold user information:
users = [
    {"id": 1, "name": "John Doe", "uses": 5},
    {"id": 2, "name": "Jane Doe", "uses": 3},
    {"id": 3, "name": "Jim Doe", "uses": 7},
]

users is a list of dictionaries, holding information for each user. In this sample code, we have the information of 3 users as initial values.

  • Endpoint to get a specific user:
@app.get("/users/{user_id}")
async def read_user(user_id: int):
    for users in users:
        if user["id"] == user_id:
            return user
    return {"message": "User not found"}
  • Endpoint to get information about all users:
@app.get("/users")
async def read_users():
    return users
  • Endpoint to create new users:
@app.post("/users")
async def create_user(user: User):
    users.append({"id": len(users) + 1, "name": user.name, "uses": user.uses})
    return users[-1]
  • Endpoint to update existing user information:
@app.put("/users/{user_id}")
async def update_user(user_id: int, user: User):
    for u in users:
        if u["id"] == user_id:
            u["name"] = user.name
            u["uses"] = user.uses
            return u
    return {"message": "User not found"}
  • Endpoint to delete user information:
@app.delete("/users/{user_id}")
async def delete_user(user_id: int):
    for u in users:
        if u["id"] == user_id:
            users.remove(u)
            return {"message": f"User {user_id} has been deleted."}
    return {"message": "User not found"}

These endpoints are defined using FastAPI’s decorator functions, and include HTTP methods (get, post, put, delete) and URL paths (/users/{user_id} and / users). Also, the endpoint functions have the async keyword to enable asynchronous processing.

You should have started your FastAPI application with the following command:

uvicorn main:app --reload

test

# test GET request
curl http://localhost:8000/users
# test the POST request
curl -X POST -H "Content-Type: application/json" -d '{"name":"John Doe"}' http://localhost:8000/users
# test the PUT request
curl -X PUT -H "Content-Type: application/json" -d '{"name":"Jane Smith"}' http://localhost:8000/users/1
# test DELETE request
curl -X DELETE http://localhost:8000/users/1

summary

FastAPI makes it easy to define routes using decorators. In this article, we introduced how to create a routing process for FastAPI. Specifically, it defined how a request from a client would be handled, a combination of an HTTP method and a URL path.

I also showed an example of using the GET method to retrieve information for a specific user and returning the “uses” information along with it. By now you should know how to use FastAPI to create flexible APIs.

FastAPI is a modern, fast, web framework with a powerful type system based on Python’s type hints. This also facilitates the development of large applications.