FastAPI是一个高性能的Web框架,它可以帮助开发者快速构建RESTful API。它使用Python 3.6+的最新功能,如函数签名和异步函数,来创建API。
FastAPI可以获取请求体中的数据,并将其解析为Python对象。它使用Pydantic库来定义请求体中的数据结构,并将其映射到Python对象。例如,如果我们想要从请求体中获取一个JSON对象,我们可以使用Pydantic库来定义JSON对象的结构:
from pydantic import BaseModel class User(BaseModel): name: str age: int然后我们可以在FastAPI函数中使用这个User类来获取请求体中的JSON对象:
@app.post("/user") def create_user(user: User): return user当请求到达时,FastAPI会将请求体中的JSON对象映射到User类的实例上。这样我们就可以在函数内部使用这个User实例了。
使用 FastAPI,你可以定义、校验、记录文档并使用任意深度嵌套的模型(归功于Pydantic)。
你可以将一个属性定义为拥有子元素的类型。例如 Python list:
from typing import Optional
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
name: str
description: Optional[str] = None
price: float
tax: Optional[float] = None
tags: list = []
@app.put("/items/{item_id}")
async def update_item(item_id: int, item: Item):
results = {"item_id": item_id, "item": item}
return results
这将使 tags 成为一个由元素组成的列表。不过它没有声明每个元素的类型。
但是 Python 有一种特定的方法来声明具有子类型的列表:
首先,从 Python 的标准库 typing 模块中导入 List:
from typing import List, Optional
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
name: str
description: Optional[str] = None
price: float
tax: Optional[float] = None
tags: List[str] = []
@app.put("/items/{item_id}")
async def update_item(item_id: int, item: Item):
results = {"item_id": item_id, "item": item}
return results
要声明具有子类型的类型,例如 list、dict、tuple:
from typing import List
my_list: List[str]
这完全是用于类型声明的标准 Python 语法。
对具有子类型的模型属性也使用相同的标准语法。
因此,在我们的示例中,我们可以将 tags 明确地指定为一个「字符串列表」:
from typing import List, Optional
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
name: str
description: Optional[str] = None
price: float
tax: Optional[float] = None
tags: List[str] = []
@app.put("/items/{item_id}")
async def update_item(item_id: int, item: Item):
results = {"item_id": item_id, "item": item}
return results
但是随后我们考虑了一下,意识到标签不应该重复,它们很大可能会是唯一的字符串。
Python 具有一种特殊的数据类型来保存一组唯一的元素,即 set。
然后我们可以导入 Set 并将 tag 声明为一个由 str 组成的 set:
from typing import Optional, Set
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
name: str
description: Optional[str] = None
price: float
tax: Optional[float] = None
tags: Set[str] = set()
@app.put("/items/{item_id}")
async def update_item(item_id: int, item: Item):
results = {"item_id": item_id, "item": item}
return results
这样,即使你收到带有重复数据的请求,这些数据也会被转换为一组唯一项。
而且,每当你输出该数据时,即使源数据有重复,它们也将作为一组唯一项输出。
并且还会被相应地标注 / 记录文档。
Pydantic 模型的每个属性都具有类型。
但是这个类型本身可以是另一个 Pydantic 模型。
因此,你可以声明拥有特定属性名称、类型和校验的深度嵌套的 JSON 对象。
上述这些都可以任意的嵌套。
例如,我们可以定义一个 Image 模型:
from typing import Optional, Set
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Image(BaseModel):
url: str
name: str
class Item(BaseModel):
name: str
description: Optional[str] = None
price: float
tax: Optional[float] = None
tags: Set[str] = []
image: Optional[Image] = None
@app.put("/items/{item_id}")
async def update_item(item_id: int, item: Item):
results = {"item_id": item_id, "item": item}
return results
然后我们可以将其用作一个属性的类型:
from typing import Optional, Set
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Image(BaseModel):
url: str
name: str
class Item(BaseModel):
name: str
description: Optional[str] = None
price: float
tax: Optional[float] = None
tags: Set[str] = []
image: Optional[Image] = None
@app.put("/items/{item_id}")
async def update_item(item_id: int, item: Item):
results = {"item_id": item_id, "item": item}
return results
这意味着 FastAPI 将期望类似于以下内容的请求体:
{
"name": "Foo",
"description": "The pretender",
"price": 42.0,
"tax": 3.2,
"tags": ["rock", "metal", "bar"],
"image": {
"url": "http://example.com/baz.jpg",
"name": "The Foo live"
}
}
再一次,仅仅进行这样的声明,你将通过 FastAPI 获得:
除了普通的单一值类型(如 str、int、float 等)外,你还可以使用从 str 继承的更复杂的单一值类型。
要了解所有的可用选项,请查看关于 来自 Pydantic 的外部类型 的文档。你将在下一章节中看到一些示例。
例如,在 Image 模型中我们有一个 url 字段,我们可以把它声明为 Pydantic 的 HttpUrl,而不是 str:
from typing import Optional, Set
from fastapi import FastAPI
from pydantic import BaseModel, HttpUrl
app = FastAPI()
class Image(BaseModel):
url: HttpUrl
name: str
class Item(BaseModel):
name: str
description: Optional[str] = None
price: float
tax: Optional[float] = None
tags: Set[str] = set()
image: Optional[Image] = None
@app.put("/items/{item_id}")
async def update_item(item_id: int, item: Item):
results = {"item_id": item_id, "item": item}
return results
该字符串将被检查是否为有效的 URL,并在 JSON Schema / OpenAPI 文档中进行记录。
你还可以将 Pydantic 模型用作 list、set 等的子类型:
from typing import List, Optional, Set
from fastapi import FastAPI
from pydantic import BaseModel, HttpUrl
app = FastAPI()
class Image(BaseModel):
url: HttpUrl
name: str
class Item(BaseModel):
name: str
description: Optional[str] = None
price: float
tax: Optional[float] = None
tags: Set[str] = set()
images: Optional[List[Image]] = None
@app.put("/items/{item_id}")
async def update_item(item_id: int, item: Item):
results = {"item_id": item_id, "item": item}
return results
这将期望(转换,校验,记录文档等)下面这样的 JSON 请求体:
{
"name": "Foo",
"description": "The pretender",
"price": 42.0,
"tax": 3.2,
"tags": [
"rock",
"metal",
"bar"
],
"images": [
{
"url": "http://example.com/baz.jpg",
"name": "The Foo live"
},
{
"url": "http://example.com/dave.jpg",
"name": "The Baz"
}
]
}
Info
请注意 images 键现在具有一组 image 对象是如何发生的。
你可以定义任意深度的嵌套模型:
from typing import List, Optional, Set
from fastapi import FastAPI
from pydantic import BaseModel, HttpUrl
app = FastAPI()
class Image(BaseModel):
url: HttpUrl
name: str
class Item(BaseModel):
name: str
description: Optional[str] = None
price: float
tax: Optional[float] = None
tags: Set[str] = set()
images: Optional[List[Image]] = None
class Offer(BaseModel):
name: str
description: Optional[str] = None
price: float
items: List[Item]
@app.post("/offers/")
async def create_offer(offer: Offer):
return offer
Info
请注意 Offer 拥有一组 Item 而反过来 Item 又是一个可选的 Image 列表是如何发生的。
如果你期望的 JSON 请求体的最外层是一个 JSON array(即 Python list),则可以在路径操作函数的参数中声明此类型,就像声明 Pydantic 模型一样:
images: List[Image]
例如:
from typing import List
from fastapi import FastAPI
from pydantic import BaseModel, HttpUrl
app = FastAPI()
class Image(BaseModel):
url: HttpUrl
name: str
@app.post("/images/multiple/")
async def create_multiple_images(images: List[Image]):
return images
你可以随处获得编辑器支持。
即使是列表中的元素:
如果你直接使用 dict 而不是 Pydantic 模型,那你将无法获得这种编辑器支持。
但是你根本不必担心这两者,传入的字典会自动被转换,你的输出也会自动被转换为 JSON。
你也可以将请求体声明为使用某类型的键和其他类型值的 dict。
无需事先知道有效的字段/属性(在使用 Pydantic 模型的场景)名称是什么。
如果你想接收一些尚且未知的键,这将很有用。
其他有用的场景是当你想要接收其他类型的键时,例如 int。
这也是我们在接下来将看到的。
在下面的例子中,你将接受任意键为 int 类型并且值为 float 类型的 dict:
from typing import Dict
from fastapi import FastAPI
app = FastAPI()
@app.post("/index-weights/")
async def create_index_weights(weights: Dict[int, float]):
return weights
Tip
请记住 JSON 仅支持将 str 作为键。
但是 Pydantic 具有自动转换数据的功能。
这意味着,即使你的 API 客户端只能将字符串作为键发送,只要这些字符串内容仅包含整数,Pydantic 就会对其进行转换并校验。
然后你接收的名为 weights 的 dict 实际上将具有 int 类型的键和 float 类型的值。
使用 FastAPI 你可以拥有 Pydantic 模型提供的极高灵活性,同时保持代码的简单、简短和优雅。
而且还具有下列好处:
File用于定义客户端的上传文件。说明因为上传文件以「表单数据」形式发送。所以接收上传文件,要预先安装python-multipart。例如...
可以在 PyPI 搜索 标记为Framework :: Flask扩展包,并且可以通过easy_install或pip下载。如果你把一个 Flask 扩展添加...
Flask类有一个redirect()函数。调用时,它返回一个响应对象,并将用户重定向到具有指定状态代码的另一个目标位置。 redirect()函...
FastCGI是在nginx,lighttpd和Cherokee等web服务器上的Flask应用程序的另一个部署选项。配置FastCGI首先,您需要创建FastCGI服务...
class RequestFactoryRequestFactory 与测试客户端共享相同的 API。 但是,RequestFactory 不能像浏览器那样运行,而是...
代码覆盖度表示有多少源代码被测试了。它表明了代码的哪些部分被测试用例覆盖,哪些没有。这是测试应用很重要的部分,所以强烈推...
到目前为止,本文档的重点是缓存您自己的数据。但是另一种类型的缓存也与Web开发相关:由“下游”缓存执行的缓存。这些系统甚至...
模型继承在 Django 中与普通类继承在 Python 中的工作方式几乎完全相同,但也仍应遵循本页开头的内容。这意味着其基类应该继承自...