初识FastAPI(四)

本文基于Datawhale的开源学习项目wow-fullstac的子项目FastAPI
如果文中出现了错误以及不理解的地方欢迎在留言

表单数据

虽然 JSON 是最常见的数据交换格式,但某些情况下,客户端可能会传递其他类型的数据,比如表单数据(Form Data)

使用pip install python-multipart安装需要的库,Form使用方法和之前的Body一样,其实Form是继承自Body的,如果没有显示使用Form就会默认变成查询参数或者请求体参数

import uvicorn
from typing import Annotated
from fastapi import FastAPI, Form

app = FastAPI()


@app.post("/login/")
async def login(username: Annotated[str, Form()], password: Annotated[str, Form()]):
    return {"username": username}


if __name__ == "__main__":
    uvicorn.run(app)

我们在这里显示构造一个json去尝试

import requests

url = "http://127.0.0.1:8000/login/"
data = {
    'username':'jack',
    'password':123
}

response = requests.post(url,json=data)
try:
    print(response.json())
except:
    print(response.text)

返回结果

{
    "detail": [
        {
            "type": "missing",
            "loc": [
                "body",
                "username"
            ],
            "msg": "Field required",
            "input": null
        },
        {
            "type": "missing",
            "loc": [
                "body",
                "password"
            ],
            "msg": "Field required",
            "input": null
        }
    ]
}

传递json会直接报错,告诉我们在Body中缺少了usernamepassword两个字段,但是我们其实是构造了这两个字段的,为什么会报错呢?
因为使用了Form,FastAPI会进行判断,传递的Content-Type是否是application/x-www-form-urlencodedmultipart/form-data
通过修改json=datadata=data,告诉requests我们传递的是表单格式
再次运行则正常返回

{
    "username": "jack"
}

表单模型

我们当然也可以创建一个Basemodel的类,然后显示声明为Form作用是一样的

class FormData(BaseModel):
    username: str
    password: str


app = FastAPI()


@app.post("/login/")
async def login(formdata: Annotated[FormData, Form()]):
    return {"username": formdata.username}

禁止不需要的字段

通过添加model_config 的extraforbid即可

class FormData(BaseModel):
    username: str
    password: str
    model_config = {"extra": "forbid"}

请求文件

很多时候我们使用网站都会遇到上传/下载文件。那么FastAPI是怎么处理文件的呢?答案是使用FileFile是继承自Form,而Form又继承自Body所以,用法和之前是一样的,但是要注意文件在这里是以二进制形式体现的,所以要用到bytes
但是我们还有更好用的东西,那就是UploadFile,二者的优缺点如下:

特性FileUploadFile
优点
内存使用直接加载文件内容到内存,适合小文件只在内存中缓存小文件,适合大文件处理
使用简便简单,适用于小文件支持流式读取与异步操作
适合小文件处理
适合大文件处理
异步操作支持
流式读取/写入支持
缺点
内存占用对大文件处理不够高效,内存占用大较复杂,需要显式调用 read() 等方法
不适合大文件处理
使用较复杂
需要手动关闭文件
import uvicorn
from typing import Annotated

from fastapi import FastAPI, File, UploadFile

app = FastAPI()

@app.post("/files/")
async def create_file(file: Annotated[bytes, File()]):
    return {"file_size": len(file)}

@app.post("/uploadfile/")
async def create_upload_file(file: UploadFile):
    return {"filename": file.filename}


if __name__ == "__main__":
    uvicorn.run(app)

构造一个简单代码

import requests
import json

url = "http://127.0.0.1:8000/uploadfile/"

filepath = "test.txt"

with open(filepath, "rb") as f:
    files = {"file": f}
    response = requests.post(url, files=files)

try:
    print(json.dumps(response.json(), indent=4))
except:
    print(response.text)

可以得到

{
    "filename": "test.txt"
}

Uploadfile的详细用法可以参考FastAPI关于uploadfile的用法介绍

多文件上传

与之前的多参数一样,只需要添加(files: list[UploadFile]):用list即可

@app.post("/mul_uploadfiles/")
async def create_upload_files(files: list[UploadFile]):
    filenames = [file.filename for file in files]
    return {"filenames": filenames}

构造函数

import requests
import json

url = "http://127.0.0.1:8000/mul_uploadfiles/"

file1path = "test.txt"
file2path = "test2.txt"
with open(file1path, "rb") as f1, open(file2path, "rb") as f2:
    files = [
        ("files", ("test.txt", f1)),
        ("files", ("test2.txt", f2)),
    ]
    response = requests.post(url, files=files)

try:
    print(json.dumps(response.json(), indent=4))
except:
    print(response.text)

返回结果

{
    "filenames": [
        "test.txt",
        "test2.txt"
    ]
}

请求表单与文件

FastAPI 支持同时使用 File 和 Form 定义文件和表单字段。

import uvicorn
from typing import Annotated

from fastapi import FastAPI, File, Form, UploadFile

app = FastAPI()


@app.post("/files/")
async def create_file(
    file: Annotated[UploadFile, File()],
    token: Annotated[str, Form()],
):
    return {
        "token": token,
        "filename": file.filename,
    }


if __name__ == "__main__":
    uvicorn.run(app)

构造函数

import requests
import json

url = "http://127.0.0.1:8000/files/"

file1path = "test.txt"
data = {"token": "this is test.txt"}
with open(file1path, "rb") as f:
    file = {
        ("file", ("test.txt", f)),
    }
    response = requests.post(url, data=data, files=file)

try:
    print(json.dumps(response.json(), indent=4))
except:
    print(response.text)

返回结果

{
    "token": "this is test.txt",
    "filename": "test.txt"
}
03-13
### FastAPI 框架概述 FastAPI 是一种现代、快速(高性能)的 Web 框架,用于构建 API,基于 Python 类型提示实现自动化的数据验证功能。它利用 Pydantic 库来提供强大的数据校验能力,并通过 Starlette 提供异步支持[^1]。 以下是关于 FastAPI 的详细介绍: --- ### 初识 FastAPI 创建一个基本的 FastAPI 应用程序非常简单。首先需要导入 `FastAPI` 并实例化该类的一个对象。例如,在下面的例子中,变量 `app` 就是一个 FastAPI 实例: ```python from fastapi import FastAPI app = FastAPI() ``` --- ### 请求参数与验证 FastAPI 支持多种类型的请求参数,包括路径参数、查询参数以及表单数据等。这些参数可以通过类型声明和默认值的方式定义,同时可以指定额外的约束条件,比如最小长度或最大长度。以下是一个简单的例子,展示了如何使用 `Query` 函数设置查询字符串参数并对其进行验证[^3]: ```python from fastapi import FastAPI, Query app = FastAPI() @app.get("/items/") async def read_items(q: str = Query(None, min_length=3, max_length=50)): results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]} if q: results.update({"q": q}) return results ``` 在这个示例中,`q` 参数被设定为可选,默认值为 `None`,并且其有效范围是从 3 字符到最多 50 字符之间。 --- ### 响应处理与配置 除了输入数据外,FastAPI 还能够轻松管理返回给客户端的数据结构及其格式。开发者可以直接返回字典或其他序列化后的 JSON 数据作为 HTTP 响应体的一部分[^2]。 --- ### 配置依赖注入系统 为了增强灵活性和重用性,FastAPI 设计了一套完善的 **依赖注入机制** (Dependency Injection System),允许用户将复杂的逻辑分解成更小的部分以便于维护和发展。 #### 示例代码展示依赖注入: ```python from typing import Optional from fastapi import Depends, FastAPI fake_db = {} class FixedContentQueryChecker: def __init__(self, allowed_query: Optional[str] = None): self.allowed_query = allowed_query def __call__(self, query: str = "") -> None: if self.allowed_query and query != self.allowed_query: raise ValueError(f"Query '{query}' does not match the fixed value") checker = FixedContentQueryChecker(allowed_query="fixedvalue") @app.get("/dependent-items/") async def dependent_read_items(query_checker=Depends(checker), q: str = ""): await query_checker(q) return fake_db[q] ``` 上述片段说明了如何自定义依赖项并通过 `Depends()` 方法将其应用于路由处理器之中。 --- ### 安全认证与授权 当涉及到敏感资源访问控制时,安全措施必不可少。FastAPI 提供了一些内置工具帮助完成 OAuth2 流程以及其他形式的身份验证方案。 --- ### 数据库操作与项目架构设计建议 对于实际生产环境下的应用程序来说,连接外部存储服务几乎是不可避免的任务之一。因此学习怎样有效地集成 SQLAlchemy 或 Tortoise ORM 至 FastAPI 中显得尤为重要。 另外还应该考虑采用模块化的方式来规划整个项目的文件夹布局,使得不同组件之间的职责更加清晰明了。 --- ### 总结 综上所述,FastAPI 不仅提供了简洁优雅的语法糖衣包裹着强大性能表现的核心引擎,而且围绕 RESTful APIs 构建了一系列实用的功能特性集合。无论是新手还是经验丰富的工程师都可以从中受益匪浅! ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值