FastAPI First Application
This section uses a complete example to walk you through creating a FastAPI application from scratch and understanding what each line of code means.
Minimal application
Create one namedmain.pyfile, add the following code:
Example
# Step 1: Import the FastAPI class
# Step 2: Create the application instance
app = FastAPI()
# Step 3: Define the path operation decorator
# Step 4: Define the path operation function
@app.get("/")
async def root():
# Step 5: Return the response content
return {"message": "Hello World"}
Start the application:
$ uvicorn main:app --reload
Visithttp://127.0.0.1:8000, returns:
{"message": "Hello World"}
Code breakdown
1. Import FastAPI
from fastapi import FastAPI
FastAPIIt is a Python class that provides all the core functionality for your API. It directly inherits from Starlette, so you can also use all of Starlette's features.
2. Create the app instance
app = FastAPI()
create a FastAPI instance, typically with the variable nameapp. This instance is the main interaction object for creating all APIs. Unlike Flask, FastAPI does not need to pass__name__parameters.
3. Define the path operation decorator
@app.get("/")
This line of code tells FastAPI: when a user accesses throughGETMethod to access the root path/, the function below is executed.
This involves two concepts:
| Concepts | Description | Example |
|---|---|---|
| Path | from the first ... in the URL/the latter part of the path, also known as the "endpoint" or "route" | /items/foo |
| Operation | HTTP methods correspond to different operational semantics | GET、POST、PUT、DELETE |
FastAPI supports decorators for all HTTP methods:
| decorator | HTTP Methods | Common uses |
|---|---|---|
@app.get() | GET | Get/read data |
@app.post() | POST | Create new data |
@app.put() | PUT | Completely update data |
@app.patch() | PATCH | Partially update data |
@app.delete() | DELETE | Delete data |
4. Define the path operation function
async def root():
This is the path operation function; whenever FastAPI receivesGET /a request, it will call it. You can name the function whatever you like, but it's recommended to choose a meaningful name.
You can useasync defor ordinarydefto define the function. FastAPI automatically handles the difference between the two. If you're not familiar with async programming, use regulardefand that's fine; later chapters will cover async in detail.
5. Return the response content
return {"message": "Hello World"}
The function returns a dictionary, and FastAPI automatically converts it to a JSON response. You can returndict、list、str、intsuch types, and FastAPI will automatically handle JSON conversion.
Add more routes
Next, let's add path parameters and query parameters to enrich the application's functionality:
Example
app = FastAPI()
@app.get("/")
async def root():
"""Root path, returns welcome message"""
return {"message": "Hello World"}
@app.get("/items/{item_id}")
async def read_item(item_id: int, q: str | None = None):
"""Retrieve an item by ID, with optional query parameter q"""
return {"item_id": item_id, "q": q}
Parameter description for the newly added route:
| Parameter | Type | Source | Description |
|---|---|---|---|
item_id | int | Path Parameter | obtained from the URL path; FastAPI automatically converts the string to an integer |
q | str | None | Query Parameter | From the URL's?q=xxxretrieved from a part, with a default value ofNone, meaning optional |
Access test:
# 访问根路径
GET http://127.0.0.1:8000/
响应: {"message": "Hello World"}
# 访问带路径参数的路由
GET http://127.0.0.1:8000/items/5
响应: {"item_id": 5, "q": null}
# 同时传递路径参数和查询参数
GET http://127.0.0.1:8000/items/5?q=example
响应: {"item_id": 5, "q": "example"}
Noteitem_idThe value is an integer5Instead of a string"5"this is FastAPI's data conversion feature based on type declarations. If a non-integer is passed (e.g.,/items/foo), FastAPI returns a clear validation error message.
Add a POST request
Below, we add a POST route that uses a request body:
Example
from pydantic import BaseModel
app = FastAPI()
# Define the request body data model
class Item(BaseModel):
name: str # Required: Product name
description: str | None = None # Optional: Product description
price: float # Required: Product price
tax: float | None = None # Optional: tax
@app.post("/items/")
async def create_item(item: Item):
"""Create a new product, accepts a JSON request body."""
return item
@app.put("/items/{item_id}")
async def update_item(item_id: int, item: Item):
"""Update the specified product, using both path parameters and request body"""
return {"item_id": item_id, "item_name": item.name}
Here, we use Pydantic'sBaseModelto define the structure of the request body. FastAPI will automatically:
- parse the JSON data from the request into
ItemObject - Validate data types and required fields
- display the request body structure in the API documentation
Pydantic is a core dependency of FastAPI, used for data validation and serialization. Later chapters will cover its usage in detail.
FastAPI parameter recognition rules
FastAPI automatically identifies parameter sources using the following rules:
| Parameter source | Recognition condition | Example |
|---|---|---|
| Path Parameter | The parameter name appears in the route path's{}Medium | item_idIn/items/{item_id}Medium |
| Query Parameter | The parameter is a single type (int、str、booletc.) | q: str | None = None |
| request body | the parameter type is a Pydantic model | item: Item |
You can mix these three kinds of parameters in the same function, and FastAPI will automatically get data from the correct location.
Summary
Core steps for creating a FastAPI application:
- Import
FastAPI - Create the app instance
app = FastAPI() - Using decorators (such as
@app.get()) to define path operations - Define path operation functions and declare parameters using type annotations.
- Usage
uvicorn main:app --reloadRun the development server