【FastAPI】1

安装

pip install "fastapi[standard]"

创建main.py

app = FastAPI() 命名,如果更改命名,后续运行命令需要指定

from typing import Union
from fastapi import FastAPI

app = FastAPI()

@app.get("/")
def read_root():
    return {"Hello": "World"}

@app.get("/items/{item_id}")
def read_item(item_id: int, q: Union[str, None] = None):
    return {"item_id": item_id, "q": q}

运行

  • fastapi dev main.py

    运行fastapi dev main.py 命令后,服务器会在main.py模块中找名为 app 的变量,

    使用了fastapi dev,修改并保存main.py代码时,服务器会自动重启,不需要手动Ctrl+C再重新运行,

    如果代码中变量命名为web_api = FastAPI() ,需要在运行时指定 fastapi dev main.py --app web_api

  • fastapi run main.py

    正式部署时要改用fastapi run,此模式下不会监控文件变化,更安全

类型声明

普通: def get_full_name(first_name, last_name)

添加类型提示: def get_full_name(first_name: str, last_name: str)

[!NOTE]

因为编辑器知道变量的类型,不仅能获得代码补全,还能得到错误检查

有些数据结构内部也可以有自己的类型,拥有内部类型的类型为通用类型:dict、list、set、tuple。要声明这些类型和内部类型,使用标准模块typing

[!NOTE]

内部类型用方括号表示

  • def process_items(items: list[str])

    变量items是list,而列表中的每个项都是str

  • def process_items(items_t: tuple[int, int, str], items_s: set[bytes])

    变量 items_t 是 tuple,包含3个元素:int、另一个 int 和 str

    变量 items_s 是 set ,其每个项类型为 bytes

  • def process_items(items: dict[str, float])

    变量 items 是 dict,key 的类型是 str,value 的类型的float

  • def process_item(item: int | str) (python3.10+)

    def process_item(item: Union[int, str])(python3.9+)

    变量 item 可以是多种类型中的一种,int 或者 str

  • def say_hi(item: Optional[str] = None)

    def say_hi(item: Union[str, None] = None)

    def say_hi(item: str | None = None)

    变量 item 可以是 str,也可以是 None。optional[somthing]Union[Somthing,None] 的捷径,他们是等价的

    [!Note]

    没有默认值的参数,FastAPI会认为是必填项

    声明后面需要有= None,否则会报错:相当于只说可以是int也可以是str,但没有说如果不传就默认是None

  • def get_person_name(one_person: Person)

    可以声明一个类作为变量的类型,one_person 是 Person 类的实例

  • Annotated在不改变变量类型的前提下,给变量捆绑额外的指令或说明

    • 格式: 变量名: Annotated[类型, 约束条件] = 默认值
      def read_items(q: Annotated[str | None, Query(max_length=50)] = None)

    • 可以通过元数据(QueryPathBody)限制输入的数据

      • 字符串限制:长度、正则匹配

      • 字数限制:大于(gt)、小于(lt)、大于等于(ge)、小于等于(le)

        # 限制 item_id 必须在 1 到 1000 之间
        @app.get("/items/{item_id}")
        async def read_items(
            item_id: Annotated[int, Path(title="商品的ID", ge=1, le=1000)]
        ):
            return {"item_id": item_id}
        
    • 可预定义带有约束的类型,重复使用

      # 定义一个通用的“用户名”类型:必须是字符串,长度 3-20; 之后更改用户名长度,只需修改一处
      Username = Annotated[str, Query(min_length=3, max_length=20, pattern="^[a-zA-Z0-9_-]+$")]
      
      @app.get("/user")
      async def get_user(name: Username): ...
      
      @app.post("/user")
      async def create_user(name: Username): ...
      
    • 支持依赖注入。把复杂逻辑(如权限检查、数据库连接)封装。

      # 定义一个获取当前用户的依赖
      CurrentUser = Annotated[User, Depends(get_current_active_user)]
      
      @app.get("/items")
      async def read_items(user: CurrentUser): # 自动完成登录检查并获取用户对象
          return {"user_email": user.email}
      

    [!NOTE]

    参数元数据:Query、Path、Body。作用是显式地告诉FastAPI去哪里获取数据并要遵守什么校验规则。

    1. Query(查询参数)

      位置:URL 问号后面,例如/items/?q=iphone&page=1

      用途:用于过滤、排序、分页等可选操作

      常用约束:min_length、max_length、alias(别名)

    2. Path(路径参数)

      位置:URL 路径之中,例如/items/{item_id}

      用途:用于定位特定的资源

      特点:参数名必须与路径大括号中的名字完全一致

      常用约束:ge(>=)、gt(>)、le(<=)、lt(<)

    3. Body(请求体)

      位置:HTTP请求的Body中,通常以JSON格式发送。

      用途:用于提交、创建或更新数据。通常配合Pydantic模型使用Body

并发与异步

如果想在函数内部使用await,这个函数必须被声明为 async def

只有被定义为 async def 的函数才能被 await 调用

  • 想用await,被调用的函数必须是 async def
  • 被调用函数是 async def ,调用它时必须加 await
  • 函数里没有 await 任何东西,通常不需要写成 async def

异步函数不能直接调用: burger = get_burger(2) ,而是加上await,正确写法 burger = await get_burger(2)

[!NOTE]

如果直接调用 async def 定义的函数,只是拿到了一个协程对象,相当于取餐凭证而不是汉堡本身,

加上 await ,才代表正在等待结果,最终才会拿到真实的数据也就是汉堡

操作

操作指HTTP方法,包括 GETPUTPOSTDELETE 以及 PATCHOPTIONSHEADTRACE

  • POST 创建数据

  • GET 读取数据

  • PUT 更新数据

  • DELETE 删除数据

from fastapi import FastAPI

app = FastAPI()

# '@app'指FastAPI实例,'.get'指HTTP方法,'("/")'指路径地址
@app.get("/")	# 告诉FastAPI,通过GET方法访问'/'时,就由下面的函数来处理
async def root():
    return {"message": "Hello World"}

[!NOTE]

FastAPI 是按照代码从上到下的顺序进行匹配的。 只要找到第一个匹配成功的路径,它就会停止寻找并执行。因此,静态路径(如 /me)永远要写在动态路径(如 /{user_id})的前面

查询参数

声明不属于路径参数的函数参数时,会被自动解释为查询参数

路径参数:如果参数名出现在了 @app.get("/items/{item_id}") 的大括号里,它就是路径参数。

查询参数:如果参数名没有出现在大括号里,它就被自动当成查询参数。

@app.get("/students/{student_id}")
def read_student(student_id: int, score: int = 0): 
	# URL:/students/101?score=95;大括号里有student_id,它是路径参数;而score是查询参数
	# FastAPI 会自动去 URL 问号 ? 后面寻找 score=xxx
    return {"id": student_id, "score": score}

[!NOTE]

  1. 自动转换类型:如果定义 score: int,用户传 ?score=abc,FastAPI 会报错,因为它知道查询参数也需要是数字。

  2. 默认值支持:可以写 score: int = 20。如果用户没传 ?score,它就自动用 20。

  3. 可选参数:可以写 q: str | None = None,这样 ?q=xxx 传不传都行。

posted @ 2026-01-12 16:09  wasline  阅读(23)  评论(0)    收藏  举报