)
数据校验借助 Pydantic使用标准的 Python 类型来声明请求体。from fastapi import FastAPI from pydantic import BaseModel app FastAPI() class Item(BaseModel): name: str price: float is_offer: bool | None None app.get(/) def read_root(): return {Hello: World} app.get(/items/{item_id}) def read_item(item_id: int, q: str | None None): return {item_id: item_id, q: q} app.put(/items/{item_id}) def update_item(item_id: int, item: Item): return {item_name: item.name, item_id: item_id}Python语法特性类型提示Python 支持可选的“类型提示”也叫“类型注解”。无类型注解def get_full_name(first_name, last_name): full_name first_name.title() last_name.title() return full_name print(get_full_name(john, doe))函数功能接收first_name和last_name。通过title()将每个参数的第一个字母转换为大写。用一个空格将它们拼接起来。引入类型注解如果需要调用“把首字母变大写的方法”。是upper是uppercasefirst_uppercase还是capitalizeIDE 完全没有提示因为IDE也不知道这个参数类型所以不知道能调用哪些方法。为了解决这个问题引入类型注解def get_full_name(first_name: str, last_name: str): full_name first_name.title() last_name.title() return full_name print(get_full_name(john, doe))因为编辑器知道变量的类型你不仅能得到补全还能获得错误检查比如传参的时候传入错误类型参数会触发检查简单类型注解def get_items(item_a: str, item_b: int, item_c: float, item_d: bool, item_e: bytes): return item_a, item_b, item_c, item_d, item_e注意Python3 ❌ 没有 long 类型Python3 的int就是任意精度的整数 可以直接接收数据库 BIGINT 类型数据typing模块在一些额外的用例中你可能需要从标准库的typing模块导入内容。比如当你想声明“任意类型”时可以使用typing中的Anyfrom typing import Any def some_function(data: Any): print(data)泛型类型有些类型可以在方括号中接收“类型参数”type parameters用于声明其内部值的类型。比如“字符串列表”可以写为list[str]。列表def process_items(items: list[str]): for item in items: print(item)元组集合def process_items(items_t: tuple[int, int, str], items_s: set[bytes]): return items_t, items_s字典def process_items(prices: dict[str, float]): for item_name, item_price in prices.items(): print(item_name) print(item_price)Union可以声明一个变量可以是若干种类型中的任意一种比如既可以是int** 也可以是str。定义时使用竖线|把两种类型分开。这称为“联合类型”union**因为变量可以是这两类类型集合的并集中的任意一个。def process_item(item: int | str): print(item)Nonedef say_hi(name: str | None None): if name is not None: print(fHey {name}!) else: print(Hello World)类型作为类型class Person: def __init__(self, name: str): self.name name def get_person_name(one_person: Person): return one_person.namePydantic 模型Pydantic 是一个用于执行数据校验的 Python 库。FastAPI完全建立在 Pydantic 之上。你将数据的“结构”声明为带有属性的类。每个属性都有一个类型。然后你用一些值创建这个类的实例它会校验这些值并在需要时把它们转换为合适的类型返回一个包含所有数据的对象。你还能对这个结果对象获得完整的编辑器支持。from datetime import datetime from pydantic import BaseModel class User(BaseModel): id: int name: str John Doe signup_ts: datetime | None None friends: list[int] [] external_data { id: 123, signup_ts: 2017-06-01 12:22, friends: [1, 2, b3], } user User(**external_data) print(user) # User id123 nameJohn Doe signup_tsdatetime.datetime(2017, 6, 1, 12, 22) friends[1, 2, 3] print(user.id) # 123带元数据注解的类型提示Python 还提供了一个特性可以使用Annotated在这些类型提示中放入额外的元数据。你可以从typing导入Annotated。from typing import Annotated def say_hello(name: Annotated[str, this is just metadata]) - str: return fHello {name}Python 本身不会对这个Annotated做任何处理。对于编辑器和其他工具类型仍然是str。但你可以在Annotated中为FastAPI提供额外的元数据来描述你希望应用如何行为。重要的是要记住传给Annotated的第一个类型参数才是实际类型。其余的只是给其他工具用的元数据。现在你只需要知道Annotated** 的存在并且它是标准 Python。**async/await如果你正在使用第三方库它们会告诉你使用await关键字来调用它们就像这样# 阻塞等待这个函数操作完 异步函数必须等待执行完才能在下面拿到结果 results await some_library()然后通过async def声明你的路径操作函数app.get(/) async def read_results(): results await some_library() return results如果你正在使用一个第三方库和某些组件比如数据库、API、文件系统...进行通信第三方库又不支持使用await目前大多数数据库三方库都是这样这种情况你可以像平常那样使用def声明一个路径操作函数就像这样app.get(/) def results(): results some_library() return resultsPython 的现代版本支持通过一种叫协程——使用async和await语法的东西来写”异步代码“。Starlette 和FastAPI 是基于 AnyIO 实现的这使得它们可以兼容 Python 的标准库 asyncio 和 Trio。FastAPI 中推荐请求处理方法全部使用async def来声明