【Python】FastAPI:路径操作

RESTful 规范

RESTful(Representational State Transfer)是一种用于设计网络应用程序API的架构风格。它基于HTTP协议,强调资源的表示和状态转移,采用统一的接口设计,提供一种简洁、可扩展的通信方式。RESTful API 的核心原则是通过URL(统一资源定位符)来指定资源,通过HTTP方法(GET、POST、PUT、DELETE等)来对资源进行操作。

RESTful 规范的核心原则

RESTful 规范包含以下核心原则:

  1. 资源(Resource): 资源是REST架构中的核心概念。它表示网络中的一个实体,如用户、文件、订单等。每个资源通过一个唯一的URL进行标识。例如,在电商平台中,/products 可以表示所有商品的资源,而 /products/123 表示ID为123的特定商品。

  2. 统一接口(Uniform Interface): RESTful API 使用标准化的HTTP方法来对资源进行操作,主要包括:

    • GET: 从服务器获取资源。它是幂等的,即多次调用不会改变服务器状态。
    • POST: 向服务器提交数据以创建资源。它不是幂等的,多次调用可能会创建多个资源。
    • PUT: 更新资源,通常是完整地替换资源。它是幂等的。
    • DELETE: 删除资源。它是幂等的。
    • PATCH: 部分更新资源,通常用于修改资源的部分字段。
  3. 无状态(Stateless): 每个请求应包含所有必要的信息,服务器不应保存任何客户端状态。这样可以提高系统的可扩展性和可维护性。

  4. 层次化系统(Layered System): 客户端不需要直接与服务器通信,可以通过中间层(如代理、网关)进行交互。每一层可以独立发展和扩展。

  5. 可缓存性(Cacheability): 服务器的响应应明确指明是否可以缓存,以提高效率。GET请求的响应通常是可缓存的,而POST请求的响应通常不可缓存。

  6. 表现层状态转移(HATEOAS: Hypermedia as the Engine of Application State): 客户端通过资源的超媒体链接与应用状态进行交互,服务器提供这些链接,使得客户端可以根据上下文导航API,而不需要预先了解所有API结构。

RESTful 请求与响应示例

以下是几个常见的RESTful API请求示例及其作用:

资源表示:用户(User)资源

  • 用户的集合可以表示为/users
  • 某个特定用户可以表示为/users/{user_id},例如/users/1表示ID为1的用户。

示例 1: 获取资源 (GET Request)

GET /users HTTP/1.1
Host: api.example.com
Accept: application/json

作用: 获取所有用户的列表。响应可能是用户信息的JSON数组。

响应示例:

[
    {
        "id": 1,
        "name": "John Doe",
        "email": "[email protected]"
    },
    {
        "id": 2,
        "name": "Jane Smith",
        "email": "[email protected]"
    }
]

示例 2: 获取单个资源 (GET Request)

GET /users/1 HTTP/1.1
Host: api.example.com
Accept: application/json

作用: 获取ID为1的用户的详细信息。

响应示例:

{
    "id": 1,
    "name": "John Doe",
    "email": "[email protected]"
}

示例 3: 创建资源 (POST Request)

POST /users HTTP/1.1
Host: api.example.com
Content-Type: application/json

{
    "name": "Alice Wonderland",
    "email": "[email protected]"
}

作用: 创建一个新用户。服务器将处理请求,并返回新创建用户的详细信息,通常包括生成的唯一ID。

响应示例:

{
    "id": 3,
    "name": "Alice Wonderland",
    "email": "[email protected]"
}

示例 4: 更新资源 (PUT Request)

PUT /users/1 HTTP/1.1
Host: api.example.com
Content-Type: application/json

{
    "name": "Johnathan Doe",
    "email": "[email protected]"
}

作用: 更新ID为1的用户的详细信息。这个请求通常用来替换整个用户对象。

响应示例:

{
    "id": 1,
    "name": "Johnathan Doe",
    "email": "[email protected]"
}

示例 5: 删除资源 (DELETE Request)

DELETE /users/1 HTTP/1.1
Host: api.example.com

作用: 删除ID为1的用户。

响应示例:

HTTP/1.1 204 No Content

示例 6: 部分更新资源 (PATCH Request)

PATCH /users/1 HTTP/1.1
Host: api.example.com
Content-Type: application/json

{
    "email": "[email protected]"
}

作用: 部分更新ID为1的用户信息,例如只更新用户的电子邮件地址。

响应示例:

{
    "id": 1,
    "name": "Johnathan Doe",
    "email": "[email protected]"
}

RESTful API 设计的最佳实践

  1. 使用名词表示资源: URL路径应使用名词而不是动词表示资源。例如,/users代表用户资源,/orders代表订单资源。

  2. 使用复数表示集合: 资源的集合通常用复数形式表示。例如,/users表示所有用户的集合。

  3. HTTP方法对应操作: 使用HTTP方法表示不同的操作,而不是在URL中使用动词。例如,使用GET /users获取用户列表,而不是GET /getUsers

  4. 返回合适的状态码: 确保API返回正确的HTTP状态码。例如,成功的GET请求应返回200 OK,成功的POST请求应返回201 Created,找不到资源时应返回404 Not Found

  5. 自描述的请求和响应: API的请求和响应应包含足够的信息,使客户端能够理解并正确处理。例如,使用Content-Type头来描述请求和响应的数据格式。

  6. 使用过滤和分页: 对于可能返回大量数据的资源,应支持过滤和分页。例如,GET /users?page=2&size=10可以获取第2页的10个用户。

FastAPI中的路径操作装饰器

在FastAPI中,路径操作装饰器是用于定义API端点的核心工具。通过路径操作装饰器,你可以轻松地将Python函数与特定的HTTP请求方法和URL路径绑定,从而实现相应的功能。

路径操作装饰器是FastAPI提供的装饰器,用于将HTTP请求方法(如GET、POST、PUT、DELETE等)与某个URL路径关联起来。通过这些装饰器,开发者可以指定哪些函数处理哪些类型的请求,以及如何处理请求的数据。

例如,使用@app.get("/")装饰器可以将函数绑定到处理GET /请求的路径操作上。

from fastapi import FastAPI

app = FastAPI()

@app.get("/")
async def read_root():
    return {"message": "Hello, world!"}

在上面的示例中,@app.get("/")是一个路径操作装饰器,它将read_root函数与GET /请求关联起来。

常见的路径操作装饰器

FastAPI提供了多种路径操作装饰器,对应不同的HTTP请求方法:

  • @app.get(path): 处理GET请求。通常用于获取数据。
  • @app.post(path): 处理POST请求。通常用于创建新资源。
  • @app.put(path): 处理PUT请求。通常用于更新现有资源。
  • @app.delete(path): 处理DELETE请求。用于删除资源。
  • @app.options(path): 处理OPTIONS请求。用于获取服务器支持的通信选项。
  • @app.head(path): 处理HEAD请求。与GET类似,但不返回响应体。
  • @app.patch(path): 处理PATCH请求。用于部分更新资源。

这些装饰器的使用方法类似,只需替换请求方法的名称即可。

路径操作装饰器的常用参数

路径操作装饰器可以接受多个参数,用于配置路由的行为。以下是一些常用参数及其作用:

  • path(路径参数): 定义请求的路径。例如,@app.get("/items/{item_id}")。路径中带有大括号的部分{item_id}表示一个路径参数。

  • response_model: 指定返回数据的模型,用于自动生成API文档,并确保返回的数据符合预期结构。

  • status_code: 指定响应的HTTP状态码。例如,@app.post("/items/", status_code=201)表示创建资源时返回HTTP 201状态码。

  • summary: 为路径操作添加简短的摘要说明。这将出现在自动生成的API文档中。

  • description: 为路径操作提供更详细的描述,同样显示在API文档中。

  • tags: 为路径操作添加标签,以便在文档中对API进行分类和分组。

  • deprecated: 如果设置为True,则标记该路径操作为不推荐使用,并在API文档中提示开发者。

  • responses: 自定义响应描述,包括不同状态码的响应结构和示例。

from fastapi import FastAPI
from pydantic import BaseModel

app = FastAPI()

class Item(BaseModel):
    name: str
    description: str | None = None
    price: float
    tax: float | None = None

@app.post("/items/", response_model=Item, status_code=201, summary="Create an item")
async def create_item(item: Item):
    """
    Create an item with all the information:

    - **name**: the name of the item
    - **description**: a long description of the item
    - **price**: the price of the item
    - **tax**: the tax to be applied on the item
    """
    return item

路由分发

在 FastAPI 应用中,include_router 方法用于将多个路由组合到一个主应用程序中。通过这种方式,可以将不同功能的路由分散在多个文件中进行管理,从而提高代码的可读性和可维护性。

include_router 是 FastAPI 提供的一个方法,用于将一个或多个 APIRouter 实例包含到主应用程序中。APIRouter 是 FastAPI 提供的一个类,用于定义一组路由,可以看作是一个“微型应用程序”。

使用方法

以下是使用 include_router 进行路由分发的基本步骤:

  1. 创建一个主应用程序。
  2. 定义一个或多个 APIRouter 实例,并在其中定义路由。
  3. 使用 include_router 将这些 APIRouter 实例包含到主应用程序中。

示例代码

文件结构

project/
│
├── main.py        # 主应用文件
├── users.py       # 用户相关路由
└── items.py       # 商品相关路由

users.py:

from fastapi import APIRouter

router = APIRouter()

@router.get("/users/")
async def read_users():
    return [{"username": "user1"}, {"username": "user2"}]

@router.get("/users/{user_id}")
async def read_user(user_id: int):
    return {"username": f"user{user_id}"}

items.py:

from fastapi import APIRouter

router = APIRouter()

@router.get("/items/")
async def read_items():
    return [{"item_name": "item1"}, {"item_name": "item2"}]

@router.get("/items/{item_id}")
async def read_item(item_id: int):
    return {"item_name": f"item{item_id}"}

main.py:

from fastapi import FastAPI
from users import router as users_router
from items import router as items_router

app = FastAPI()

# 使用 include_router 将 users 和 items 路由包含进来
app.include_router(users_router)
app.include_router(items_router)

@app.get("/")
async def root():
    return {"message": "Welcome to FastAPI!"}

在这个示例中,我们将用户相关的路由定义在 users.py 文件中,将商品相关的路由定义在 items.py 文件中,然后通过 include_router 方法在主应用程序 main.py 中包含这些路由。这样,/users//items/ 路径都可以正常访问。

常用参数

  • prefix: 在包含的路由前添加一个前缀。例如,如果你在 include_router 时设置 prefix="/api",那么所有的路由都会自动加上 /api 作为前缀。
  • tags: 给包含的路由打标签,这样在 API 文档中可以分组显示。
  • dependencies: 可以为包含的路由设置依赖项,这些依赖项会应用于该 APIRouter 中的所有路由。

示例

app.include_router(users_router, prefix="/users", tags=["users"])
app.include_router(items_router, prefix="/items", tags=["items"])

添加本地静态页面

除了API路由,FastAPI 还可以轻松地提供本地静态页面(如 HTML、CSS、JavaScript 文件)用于前端展示或其他静态资源的需求。

FastAPI 使用 StaticFiles 类来提供静态文件服务。可以通过 app.mount() 方法将本地的静态文件目录挂载到特定的路径下。

示例代码

假设我们有一个名为 static 的目录,里面存放了HTML、CSS 和 JavaScript 文件。

文件结构

project/
│
├── main.py        # 主应用文件
└── static/        # 静态文件目录
    ├── index.html
    ├── style.css
    └── script.js

main.py:

from fastapi import FastAPI
from fastapi.staticfiles import StaticFiles

app = FastAPI()

# 将静态文件目录挂载到 /static 路径下
app.mount("/static", StaticFiles(directory="static"), name="static")

@app.get("/")
async def root():
    return {"message": "Visit /static/index.html to see the page"}

在 FastAPI 中,app.mount() 方法用于将一个子应用程序(如静态文件服务)挂载到主应用程序的指定路径下。下面详细解释 app.mount("/static", StaticFiles(directory="static"), name="static") 中各个参数的含义:

"/static" - 挂载路径:这个参数指定了子应用程序(即静态文件服务)在主应用程序中的挂载路径。

  • "/static" 表示客户端可以通过 http://127.0.0.1:8000/static/ 来访问挂载的静态文件。这个路径可以根据需要进行修改。

StaticFiles(directory="static") - 子应用程序StaticFiles 是 FastAPI 提供的一个类,用于处理静态文件的服务。

  • directory="static":
    • 这是 StaticFiles 的一个参数,指定了本地静态文件所在的目录。在这个示例中,"static" 是一个相对于当前工作目录的路径。
    • 这个目录中的所有文件都会通过 /static 路径暴露给客户端。例如,如果目录下有一个 index.html 文件,客户端可以通过 http://127.0.0.1:8000/static/index.html 访问它。

name="static" - 路由名称name 参数为挂载的子应用程序设置一个名称,这个名称可以在应用程序内部用于引用或反向查找。

  • name="static":
    • 给这个静态文件服务取一个名称 "static"。在实际开发中,这个名称在某些情况下可能用于识别或反向解析路由。

使用 Jinja2 模板渲染动态内容(可选)

有时,静态页面可能还需要包含动态内容。FastAPI 允许使用 Jinja2 模板引擎来渲染动态HTML页面。

安装 Jinja2:

pip install jinja2

示例代码:

假设我们需要渲染一个包含动态内容的 HTML 页面。

templates/index.html:

DOCTYPE html>
<html>
<head>
    <title>{{ title }}title>
head>
<body>
    <h1>{{ message }}h1>
body>
html>

main.py:

from fastapi import FastAPI
from fastapi.staticfiles import StaticFiles
from fastapi.templating import Jinja2Templates
from starlette.requests import Request

app = FastAPI()

app.mount("/static", StaticFiles(directory="static"), name="static")

# 配置 Jinja2 模板目录
templates = Jinja2Templates(directory="templates")

@app.get("/")
async def root(request: Request):
    return templates.TemplateResponse("index.html", {"request": request, "title": "FastAPI Demo", "message": "Welcome to FastAPI with Jinja2!"})

在这个示例中,我们定义了一个 templates 目录,用于存放 Jinja2 模板文件。然后在 / 路由中,使用 TemplateResponse 渲染动态的 HTML 页面。

你可能感兴趣的:(Python全栈开发,python,fastapi,开发语言)