使用适用于 Python 的 FastAPI 构建应用程序
已发表: 2022-11-29FastAPI 是一种快速且轻量级的 Web 框架,用于使用 Python 3.6 及更高版本构建现代应用程序编程接口。 在本教程中,我们将介绍使用 FastAPI 构建应用程序的基础知识,您将了解为什么它被提名为 2021 年最佳开源框架之一。
一旦您准备好开发您自己的 FastAPI 应用程序,您将无需寻找很远的地方来托管它们。 Kinsta 的应用程序托管和数据库托管服务提供了一个强大的 Python 平台即服务。
让我们先学习基础知识。
FastAPI的优势
下面是 FastAPI 框架给项目带来的一些优势。
- 速度:顾名思义,FastAPI 是一个非常快速的框架。 它的速度可与 Go 和 Node.js 相媲美,后者通常被认为是构建 API 的最快选项之一。
- 易于学习和编码: FastAPI 已经知道了制作可用于生产的 API 所需的几乎所有内容。 作为使用 FastAPI 的开发人员,您不需要从头开始编写所有代码。 只需几行代码,您就可以准备好部署的 RESTful API。
- 全面的文档: FastAPI 使用 OpenAPI 文档标准,因此可以动态生成文档。 本文档提供了有关 FastAPI 的端点、响应、参数和返回代码的详细信息。
- 错误更少的 API: FastAPI 支持自定义数据验证,这允许开发人员构建错误更少的 API。 FastAPI 的开发人员吹嘘该框架导致更少的人为错误——减少多达 40%。
- 类型提示: types 模块是在 Python 3.5 中引入的。 这使您能够声明变量的
type
。 当声明变量的类型时,IDE 能够提供更好的支持并更准确地预测错误。
如何开始使用 FastAPI
要按照本教程开始使用 FastAPI,您需要先做几件事。
确保您拥有程序员的文本编辑器/IDE,例如 Visual Studio Code。 其他选项包括 Sublime Text 和 Espresso。
让您的 Python 应用程序及其实例在虚拟环境中运行是一种常见的做法。 虚拟环境允许不同的包集和配置同时运行,并避免因包版本不兼容而导致的冲突。
要创建虚拟环境,请打开终端并运行以下命令:
$ python3 -m venv env
您还需要激活虚拟环境。 执行此操作的命令将根据您使用的操作系统和 shell 而有所不同。 以下是许多环境的一些 CLI 激活示例:
# On Unix or MacOS (bash shell): /path/to/venv/bin/activate # On Unix or MacOS (csh shell): /path/to/venv/bin/activate.csh # On Unix or MacOS (fish shell): /path/to/venv/bin/activate.fish # On Windows (command prompt): \path\to\venv\Scripts\activate.bat # On Windows (PowerShell): \path\to\venv\Scripts\Activate.ps1
(一些支持 Python 的 IDE 也可以配置为激活当前的虚拟环境。)
现在,安装 FastAPI:
$ pip3 install fastapi
FastAPI 是一个用于构建 API 的框架,但要测试您的 API,您需要一个本地 Web 服务器。 Uvicorn 是一个闪电般快速的异步服务器网关接口 (ASGI) Web 服务器,适用于 Python,非常适合开发。 要安装 Uvicorn,请运行以下命令:
$ pip3 install "uvicorn[standard]"
安装成功后,在项目的工作目录中创建一个名为main.py的文件。 该文件将成为您的应用程序入口点。
一个快速的 FastAPI 示例
您将通过快速设置示例端点来测试您的 FastAPI 安装。 在您的main.py文件中,粘贴以下代码,然后保存文件:
# main.py from fastapi import FastAPI app = FastAPI() @app.get("/") async def root(): return {"greeting":"Hello world"}
上面的代码片段创建了一个基本的 FastAPI 端点。 下面是每一行的作用的总结:
-
from fastapi import FastAPI
:API 的功能由 FastAPI Python 类提供。 -
app = FastAPI()
:这将创建一个 FastAPI 实例。 -
@app.get("/")
:这是一个 python 装饰器,它向 FastAPI 指定它下面的函数负责请求处理。 -
@app.get("/")
:这是一个指定路由的装饰器。 这会在站点的路由上创建一个GET
方法。 然后结果由包装函数返回。 - 其他可能用于通信的操作包括
@app.post()
、@app.put()
、@app.delete()
、@app.options()
、@app.head()
、@app.patch()
, 和@app.trace()
。
在文件目录中,在终端中运行以下命令以启动 API 服务器:
$ uvicorn main:app --reload
在此命令中, main
是您的模块的名称。 app
对象是您的应用程序的一个实例,并被导入到 ASGI 服务器中。 --reload
标志告诉服务器在您进行任何更改时自动重新加载。
你应该在你的终端看到类似这样的东西:
$ uvicorn main:app --reload INFO: Will watch for changes in these directories: ['D:\\WEB DEV\\Eunit\\Tests\\fast-api'] INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) INFO: Started reloader process [26888] using WatchFiles INFO: Started server process [14956] INFO: Waiting for application startup. INFO: Application startup complete.
在您的浏览器中,导航到http://localhost:8000
以确认您的 API 正在运行。 您应该在页面上看到“Hello”:“World”作为 JSON 对象。 这说明使用 FastAPI 创建 API 是多么容易。 您所要做的就是定义一个路由并返回您的 Python 字典,如上面代码片段的第六行所示。
使用类型提示
如果您使用 Python,您习惯于使用基本数据类型(例如int
、 str
、 float
和bool
)来注释变量。 然而,从 Python 3.9 版本开始,引入了高级数据结构。 这使您可以使用数据结构,例如dictionaries
、 tuples
和lists
。 借助 FastAPI 的类型提示,您可以使用 pydantic 模型构建数据模式,然后使用 pydantic 模型进行类型提示并从提供的数据验证中受益。
在下面的示例中,使用简单的餐费计算器calculate_meal_fee
演示了 Python 中类型提示的使用:
def calculate_meal_fee(beef_price: int, meal_price: int) -> int: total_price: int = beef_price + meal_price return total_price print("Calculated meal fee", calculate_meal_fee(75, 19))
请注意,类型提示不会改变代码的运行方式。
FastAPI 交互式 API 文档
FastAPI 使用 Swagger UI 提供自动交互式 API 文档。 要访问它,请导航至http://localhost:8000/docs
,您将看到一个包含所有端点、方法和模式的屏幕。
这种基于浏览器的自动 API 文档由 FastAPI 提供,您无需执行任何其他操作即可利用它。
另一种基于浏览器的 API 文档,也是由 FastAPI 提供的,是 Redoc。 要访问 Redoc,请导航至http://localhost:8000/redoc
,您将在其中看到端点列表、方法及其各自的响应。
在 FastAPI 中设置路由
@app
装饰器允许您指定路由的方法,例如@app.get
或@app.post
,并支持GET
、 POST
、 PUT
和DELETE
,以及不太常见的选项HEAD
、 PATCH
和TRACE
。
使用 FastAPI 构建您的应用程序
在本教程中,您将逐步使用 FastAPI 构建 CRUD 应用程序。 该应用程序将能够:
- 创建用户
- 读取用户的数据库记录
- 更新现有用户
- 删除特定用户
要执行这些 CRUD 操作,您将创建公开 API 端点的方法。 结果将是一个可以存储用户列表的内存数据库。
您将使用 pydantic 库通过 Python 类型注释执行数据验证和设置管理。 出于本教程的目的,您将数据的形状声明为具有属性的类。
本教程将使用内存数据库。 这是为了让您快速开始使用 FastAPI 构建 API。 但是,对于生产,您可以使用您选择的任何数据库,例如 PostgreSQL、MySQL、SQLite,甚至 Oracle。
构建应用程序
您将从创建用户模型开始。 用户模型将具有以下属性:
-
id
:通用唯一标识符 (UUID) -
first_name
:用户的名字 last_name
:用户的姓氏gender
: 用户的性别roles
,这是一个包含admin
和user
角色的列表
首先在您的工作目录中创建一个名为models.py的新文件,然后将以下代码粘贴到models.py中以创建您的模型:
# models.py from typing import List, Optional from uuid import UUID, uuid4 from pydantic import BaseModel from enum import Enum from pydantic import BaseModel class Gender(str, Enum): male = "male" female = "female" class Role(str, Enum): admin = "admin" user = "user" class User(BaseModel): id: Optional[UUID] = uuid4() first_name: str last_name: str gender: Gender roles: List[Role]
在上面的代码中:
- 您的
User
类扩展BaseModel
,然后从pydantic
导入。 - 如上所述,您定义了用户的属性。
下一步是创建数据库。 用以下代码替换main.py文件的内容:
# main.py from typing import List from uuid import uuid4 from fastapi import FastAPI from models import Gender, Role, User app = FastAPI() db: List[User] = [ User( id=uuid4(), first_name="John", last_name="Doe", gender=Gender.male, roles=[Role.user], ), User( id=uuid4(), first_name="Jane", last_name="Doe", gender=Gender.female, roles=[Role.user], ), User( id=uuid4(), first_name="James", last_name="Gabriel", gender=Gender.male, roles=[Role.user], ), User( id=uuid4(), first_name="Eunit", last_name="Eunit", gender=Gender.male, roles=[Role.admin, Role.user], ), ]
在main.py 中:
- 您使用
List
类型初始化了db
,并传入了User
模型 - 您创建了一个包含四个用户的内存数据库,每个用户都具有
first_name
、last_name
、gender
和roles
等必需属性。 用户Eunit
被分配了admin
和user
角色,而其他三个用户仅被分配了user
角色。
读取数据库记录
您已成功设置内存数据库并用用户填充它,因此下一步是设置一个将返回所有用户列表的端点。 这就是 FastAPI 的用武之地。
在您的main.py文件中,将以下代码粘贴到您的Hello World
端点下方:
# main.py @app.get("/api/v1/users") async def get_users(): return db
此代码定义了端点/api/v1/users
,并创建了一个异步函数get_users
,它返回数据库db
的所有内容。
保存您的文件,然后您可以测试您的用户端点。 在终端中运行以下命令以启动 API 服务器:
$ uvicorn main:app --reload
在您的浏览器中,导航到http://localhost:8000/api/v1/users
。 这应该返回所有用户的列表,如下所示:
在此阶段,您的main.py文件将如下所示:
# main.py from typing import List from uuid import uuid4 from fastapi import FastAPI from models import Gender, Role, User app = FastAPI() db: List[User] = [ User( id=uuid4(), first_name="John", last_name="Doe", gender=Gender.male, roles=[Role.user], ), User( id=uuid4(), first_name="Jane", last_name="Doe", gender=Gender.female, roles=[Role.user], ), User( id=uuid4(), first_name="James", last_name="Gabriel", gender=Gender.male, roles=[Role.user], ), User( id=uuid4(), first_name="Eunit", last_name="Eunit", gender=Gender.male, roles=[Role.admin, Role.user], ), ] @app.get("/") async def root(): return {"Hello": "World",} @app.get("/api/v1/users") async def get_users(): return db
创建数据库记录
下一步是创建端点以在数据库中创建新用户。 将以下代码片段粘贴到您的main.py文件中:
# main.py @app.post("/api/v1/users") async def create_user(user: User): db.append(user) return {"id": user.id}
在此代码段中,您定义了端点以提交新用户并使用@app.post
装饰器创建了POST
方法。
您还创建了函数create_user
,它接受user
模型的User
,并将新创建的user
追加(添加)到数据库db
。 最后,端点返回新创建的用户id
的 JSON 对象。
您将必须使用 FastAPI 提供的自动 API 文档来测试您的端点,如上所示。 这是因为您无法使用网络浏览器发出发布请求。 导航到http://localhost:8000/docs
以使用 SwaggerUI 提供的文档进行测试。
删除数据库记录
由于您正在构建一个 CRUD 应用程序,因此您的应用程序将需要能够删除指定的资源。 在本教程中,您将创建一个端点来删除用户。
将以下代码粘贴到您的main.py文件中:
# main.py from uuid import UUID from fastapi HTTPException @app.delete("/api/v1/users/{id}") async def delete_user(id: UUID): for user in db: if user.id == id: db.remove(user) return raise HTTPException( status_code=404, detail=f"Delete user failed, id {id} not found." )
以下是该代码如何工作的逐行细分:
-
@app.delete("/api/v1/users/{id}")
:您使用@app.delete()
装饰器创建了删除端点。 路径仍然是/api/v1/users/{id}
,但随后它会检索id
,这是一个与用户 ID 对应的路径变量。 -
async def delete_user(id: UUID):
:创建delete_user
函数,它从 URL 中检索id
。 -
for user in db:
这告诉应用程序遍历数据库中的用户,并检查传递的id
是否与数据库中的用户匹配。 -
db.remove(user)
:如果id
匹配到一个用户,则删除该用户; 否则,将引发状态代码为 404 的HTTPException
。
更新数据库记录
您将创建一个端点来更新用户的详细信息。 可以更新的详细信息包括以下参数: first_name
、 last_name
和roles
。
在您的models.py文件中,将以下代码粘贴到您的User
模型下,即在User(BaseModel):
类之后:
# models.py class UpdateUser(BaseModel): first_name: Optional[str] last_name: Optional[str] roles: Optional[List[Role]]
在此片段中,类UpdateUser
扩展BaseModel
。 然后将可更新的用户参数(例如first_name
、 last_name
和roles
)设置为可选。
现在您将创建一个端点来更新特定用户的详细信息。 在您的main.py文件中,将以下代码粘贴到@app.delete
装饰器之后:
# main.py @app.put("/api/v1/users/{id}") async def update_user(user_update: UpdateUser, id: UUID): for user in db: if user.id == id: if user_update.first_name is not None: user.first_name = user_update.first_name if user_update.last_name is not None: user.last_name = user_update.last_name if user_update.roles is not None: user.roles = user_update.roles return user.id raise HTTPException(status_code=404, detail=f"Could not find user with id: {id}")
在上面的代码中,您完成了以下操作:
- 创建
@app.put("/api/v1/users/{id}")
,更新端点。 它有一个可变参数id
,对应于用户的id。 - 创建了一个名为
update_user
的方法,它接受UpdateUser
类和id
。 - 使用
for
循环检查与传递的id
关联的用户是否在数据库中。 - 检查用户的任何参数
is not None
(非空)。 如果任何参数(例如first_name
、last_name
或roles
)不为空,则更新它。 - 如果操作成功,则返回用户 ID。
- 如果找不到用户,则会引发状态代码为 404 的
HTTPException
异常和一条消息Could not find user with id: {id}
。
要测试此端点,请确保您的 Uvicorn 服务器正在运行。 如果它没有运行,请输入以下命令:
uvicorn main:app --reload
下面是测试的截图。
概括
在本教程中,您了解了适用于 Python 的 FastAPI 框架,并亲眼目睹了启动和运行 FastAPI 支持的应用程序的速度有多快。 您学习了如何使用该框架构建 CRUD API 端点——创建、读取、更新和删除数据库记录。
现在,如果您想将 Web 应用程序开发提升到一个新的水平,请务必查看 Kinsta 的应用程序托管和数据库托管平台。 与 FastAPI 一样,它非常简单。