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

from fastapi import FastAPI

# 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:

ConceptsDescriptionExample
Pathfrom the first ... in the URL/the latter part of the path, also known as the "endpoint" or "route"/items/foo
OperationHTTP methods correspond to different operational semanticsGET、POST、PUT、DELETE

FastAPI supports decorators for all HTTP methods:

decoratorHTTP MethodsCommon uses
@app.get()GETGet/read data
@app.post()POSTCreate new data
@app.put()PUTCompletely update data
@app.patch()PATCHPartially update data
@app.delete()DELETEDelete 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

from fastapi import FastAPI

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:

ParameterTypeSourceDescription
item_idintPath Parameterobtained from the URL path; FastAPI automatically converts the string to an integer
qstr | NoneQuery ParameterFrom 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 fastapi import FastAPI
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 intoItemObject
  • 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 sourceRecognition conditionExample
Path ParameterThe parameter name appears in the route path's{}Mediumitem_idIn/items/{item_id}Medium
Query ParameterThe parameter is a single type (int、str、booletc.)q: str | None = None
request bodythe parameter type is a Pydantic modelitem: 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:

  1. ImportFastAPI
  2. Create the app instanceapp = FastAPI()
  3. Using decorators (such as@app.get()) to define path operations
  4. Define path operation functions and declare parameters using type annotations.
  5. Usageuvicorn main:app --reloadRun the development server
other extensions