请求与响应

suaxi
2025-06-16 / 0 评论 / 5 阅读 / 正在检测是否收录...

1. 路径参数

(1)基本使用
@app.get("/user/{user_id}")
async def get_user(user_id):
    print(user_id, type(user_id))
    return {
        "user_id": user_id
    }


(2)声明路径参数类型

此例中参数类型为 int

@app.get("/user/{user_id}")
async def get_user(user_id: int):
    print(user_id, type(user_id))
    return {
        "user_id": user_id
    }


(3)注意定义的函数顺序问题
"""
注意定义的函数顺序问题
例:有请求路径为 /user/list 的方法,它需要置于 /user/{user/id} 之前
否则会出现请求 /user/list 方法,但请求最终落在了 /user/{user_id} 方法上的问题
"""

@app.get("/user/list")
async def get_user_list():
    return tuple([
        {
            "user": "user1"
        },
        {
            "user": "user2"
        }
    ])

@app.get("/user/{user_id}")
async def get_user(user_id: int):
    print(user_id, type(user_id))
    return {
        "user_id": user_id
    }


2. 查询参数(请求参数)

路径函数中声明不属于路径参数的其他函数参数时,它们将被自动解释为查询字符串参数,就是 url? 之后用&分割的 key-value 键值对。

from typing import Union

from fastapi import FastAPI

app = FastAPI()

"""
此例中有路径参数 user_id,查询参数 dept_id
参数 dept_id 通过 Union 声明为 str、int 类型,或者为None(不传)
"""

@app.get("/user/{user_id}")
async def get_user(user_id: int, dept_id: Union[str, int] = None):
    print(f'user_id={user_id}, dept_id={dept_id}')
    return {
        "user_id": user_id,
        "dept_id": dept_id
    }


if __name__ == '__main__':
    import uvicorn

    uvicorn.run("main:app", host="127.0.0.1", port=8088, reload=True)

1.请求参数(查询参数).png

补充:

  • 自 Python 3.5 开始,PEP484 为 Python 引入了类型注解(type hints)
  • 类型检查,防止运行时出现参数、返回值类型不符
  • 作为开发文档附加说明,方便使用者调用时传入和返回参数类型
  • 模块加入不会影响程序的运行不会报正式的错误,pycharm 支持 typing 检查错误时会出现黄色警告
  • Union 和 Optional,Optional[str]Union[str] = None 的语法糖

3. 请求体数据

FastApi 请求体数据基于 Pydantic,Pydantic 主要用于做类型强制检查(校验数据)。

(1)安装
pip install pydantic


(2)使用
from typing import Union, Optional

from fastapi import FastAPI
from pydantic import BaseModel, Field, validator

app = FastAPI()


class User(BaseModel):
    id: int
    name: str
    age: int = Field(default=0, gt=0, lt=100)
    no: int
    address: Optional[str]

    @validator('name')
    def name_validator(cls, val):
        assert len(val) >= 2, '用户名不能少于2个字'
        return val


@app.post("/user")
async def add(user: User):
    print(f'新增用户: {user}')
    return user


if __name__ == '__main__':
    import uvicorn

    uvicorn.run("main:app", host="127.0.0.1", port=8088, reload=True)

补充:

  • FastApi 会自动将定义的模型类转化为 JSON Schema
  • swagger 文档

2.请求体参数.png

  • 参数校验

    当接口请求数据为

    {
      "id": 1,
      "name": "测",
      "age": 0,
      "no": 10,
      "address": "成都"
    }

    服务端参数校验返回

    3.请求体参数校验.png


4. form 表单数据

在 FastAPI 中可以使用 Form 组件来接收表单数据

(1)安装
pip install python-multipart


(2)使用
from fastapi import FastAPI, Form

app = FastAPI()


@app.post("/user")
async def add(id: str = Form(..., regex='[a-zA-Z]'),
              name: str = Form(..., min_length=2, max_length=6)):
    print(f'新增用户: id={id}, name={name}')
    return {
        "id": id,
        "name": name
    }


if __name__ == '__main__':
    import uvicorn

    uvicorn.run("main:app", host="127.0.0.1", port=8088, reload=True)

4.form表单数据测试.png

5. 文件上传

from typing import List

from fastapi import FastAPI, File, UploadFile

app = FastAPI()


@app.post("/upload-file")
async def upload_file(file: bytes = File()):
    print(f'file_len={len(file)}')
    return "上传成功"


@app.post("/upload-files")
async def upload_files(files: List[bytes] = File()):
    print(f'files_len={len(files)}')
    return "上传成功"


# 适合大文件上传
@app.post("/upload-multi-files")
async def upload_multi_files(files: List[UploadFile] = File()):
    print(f'files_len={len(files)}')
    return "上传成功"


if __name__ == '__main__':
    import uvicorn

    uvicorn.run("main:app", host="127.0.0.1", port=8088, reload=True)


6. Request 对象

在函数中声明 Request 类型的参数,FastAPI 会自动传递 Request 对象给这个参数,可以获取其中的 header, url, cookie, session 等信息

from fastapi import FastAPI, Request

app = FastAPI()


@app.get("/request_info")
async def request_info(request: Request):
    request_info_dict = {
        "method": request.method,
        "url": request.url,
        "params": request.query_params,
        "headers": request.headers,
        "cookies": request.cookies,
        "ip": request.client.host,
        "user-agent": request.headers.get("User-Agent")
    }
    print(f'request_info_dict={request_info_dict}')
    return request_info_dict


if __name__ == '__main__':
    import uvicorn

    uvicorn.run("main:app", host="127.0.0.1", port=8088, reload=True)


7. 请求静态文件

web开发中,常涉及静态文件等资源,如css、js、图片、icon等,可在项目中新建 static 文件夹,将静态资源放入该文件夹后做如下配置

from fastapi import FastAPI
from fastapi.staticfiles import StaticFiles

app = FastAPI()

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

if __name__ == '__main__':
    import uvicorn

    uvicorn.run("main:app", host="127.0.0.1", port=8088, reload=True)


8. 响应参数

(1)response_model

FastAPI 提供了 response_model 参数,声明 return 响应体的模型

  • 将输出数据转换为 response_model 中声明的数据类型
  • 验证数据结构和类型
  • 将输出数据限制为该 model 定义的
  • 添加到 OpenAPI 中
  • 在自动文档系统中使用

以新增用户为例

from typing import Optional

from fastapi import FastAPI
from pydantic import BaseModel, Field, validator

app = FastAPI()


class User(BaseModel):
    id: int
    name: str
    age: int = Field(default=0, gt=0, lt=100)
    no: int
    address: Optional[str]

    @validator('name')
    def name_validator(cls, val):
        assert len(val) >= 2, '用户名不能少于2个字'
        return val


class UserVo(BaseModel):
    id: int
    name: str
    age: int = Field(default=0, gt=0, lt=100)
    no: int


@app.post("/user", response_model=UserVo)
async def add(user: User):
    print(f'新增用户: {user}')
    return user


if __name__ == '__main__':
    import uvicorn

    uvicorn.run("main:app", host="127.0.0.1", port=8088, reload=True)

1.response_model.png

(2)response_model_exclude_unset
from typing import Optional

from fastapi import FastAPI
from pydantic import BaseModel, Field, validator

app = FastAPI()


class User(BaseModel):
    id: int
    name: str
    age: int = Field(default=0, gt=0, lt=100)
    no: int
    address: Optional[str] = None

    @validator('name')
    def name_validator(cls, val):
        assert len(val) >= 2, '用户名不能少于2个字'
        return val


@app.post("/response_model_exclude_unset_user", response_model=User, response_model_exclude_unset=True)
async def response_model_exclude_unset_add(user: User):
    print(f'新增用户: {user}')
    return user


if __name__ == '__main__':
    import uvicorn

    uvicorn.run("main:app", host="127.0.0.1", port=8088, reload=True)

2.response_model_exclude_unset.png

(3)response_model_exclude_defaults

不返回为默认值的字段

(4)response_model_exclude_none

不返回为 None 的字段

(5)INCLUDE和EXCLUDE

INCLUDE:只返回 INCLUDE 声明了的字段

EXCLUDE:返回 EXCLUDE 声明了的之外的字段(即排除指定字段)

0

评论 (0)

取消