Python Web 应用:使用 FastAPI 与 Tortoise ORM 的异步数据库操作
Python Web 应用:使用 FastAPI 与 Tortoise ORM 的异步数据库操作
目录
- 🛠 安装与配置 Tortoise ORM
- ⚡ 异步数据库操作:适配 FastAPI 的异步特性
1. 🛠 安装与配置 Tortoise ORM
Tortoise ORM 是一个非常轻量的异步 ORM 库,专为 Python 的异步框架(如 FastAPI 和 Starlette)设计。与传统的同步 ORM 不同,Tortoise ORM 支持异步数据库操作,这使得它在高并发的 Web 应用中非常适用,尤其在结合 FastAPI 的异步特性时能够最大化地提高性能和吞吐量。
安装 Tortoise ORM
要在 FastAPI 项目中使用 Tortoise ORM,首先需要安装 Tortoise ORM 和相关的数据库驱动。安装方式如下:
pip install tortoise-orm
pip install databases # 用于异步支持
pip install asyncpg # 如果使用 PostgreSQL 作为数据库
databases
库为异步数据库连接提供支持,而 asyncpg
是用于 PostgreSQL 的异步数据库驱动。如果你使用的是 SQLite 或 MySQL,可以根据需要安装不同的数据库驱动。
配置 Tortoise ORM
在 FastAPI 项目中配置 Tortoise ORM 是一个非常简单的过程,以下是配置数据库连接的步骤:
- 设置数据库 URL
首先,在settings.py
或应用的配置文件中设置数据库连接 URL。例如,如果使用 PostgreSQL:
DATABASE_URL = "postgresql://user:password@localhost:5432/dbname"
- 初始化 Tortoise ORM
然后,使用 FastAPI 的生命周期事件(例如startup
和shutdown
)来初始化和关闭数据库连接。在应用启动时初始化 Tortoise ORM,关闭时清理连接。
from fastapi import FastAPI
from tortoise import Tortoise
app = FastAPI()
@app.on_event("startup")
async def startup():
await Tortoise.init(
db_url="postgresql://user:password@localhost:5432/dbname",
modules={"models": ["app.models"]} # "app.models" 是模型所在的模块
)
await Tortoise.generate_schemas() # 创建数据库表
@app.on_event("shutdown")
async def shutdown():
await Tortoise.close_connections() # 关闭数据库连接
在上述代码中:
Tortoise.init()
用于初始化数据库连接,并指定数据库 URL 和模型的模块路径。Tortoise.generate_schemas()
用于根据模型生成数据库表结构。Tortoise.close_connections()
用于在应用关闭时清理数据库连接。创建数据库模型
Tortoise ORM 使用 Python 类定义数据库模型,这些类会映射到数据库中的表。模型类继承自 tortoise.models.Model
,并通过定义字段和属性来描述数据库的结构。以下是一个示例模型类:
from tortoise import fields
from tortoise.models import Model
class User(Model):
id = fields.IntField(pk=True) # 主键
name = fields.CharField(max_length=255)
email = fields.CharField(max_length=255, unique=True)
def __str__(self):
return self.name
在上面的代码中:
id
是一个整型字段,标记为主键。name
和 email
是字符串字段,其中 email
被设置为唯一(unique=True
)。这些模型类在 Tortoise.init()
初始化时,会自动映射为数据库中的表结构。
2. ⚡ 异步数据库操作:适配 FastAPI 的异步特性
FastAPI 是一个异步 Web 框架,它利用 Python 的 asyncio
提供的异步编程模型,能够处理大量并发请求。当 FastAPI 与 Tortoise ORM 配合使用时,能够提供非阻塞的数据库操作,从而提升系统的性能和响应速度。通过 Tortoise ORM 提供的异步查询和操作,可以实现高效的数据库交互。
异步 CRUD 操作
由于 Tortoise ORM 是基于 asyncio
实现的,因此所有的数据库操作都需要在异步函数中执行。这与传统的同步 ORM 不同,后者依赖于阻塞调用。以下是如何在 FastAPI 中使用异步 CRUD 操作与 Tortoise ORM 配合进行数据库交互。
创建数据(Create)
首先,创建一个数据项,以下是一个简单的 POST 请求示例,用于创建一个新的用户:
from fastapi import FastAPI, HTTPException
from tortoise.exceptions import DoesNotExist
from app.models import User
@app.post("/users/")
async def create_user(name: str, email: str):
user = await User.create(name=name, email=email) # 使用异步操作创建用户
return {"id": user.id, "name": user.name, "email": user.email}
在上述代码中,await User.create()
是一个异步操作,它将执行数据库插入操作,而不会阻塞主线程。
查询数据(Read)
使用 Tortoise ORM 查询数据也非常简单,以下是如何查询所有用户并返回结果:
@app.get("/users/")
async def get_users():
users = await User.all() # 异步查询所有用户
return users
await User.all()
是异步执行的,它将从数据库中查询所有的用户并返回。由于查询是异步的,它不会阻塞其他请求的处理。
你还可以使用 filter
和 get
方法来查询特定条件的用户。例如,查询具有特定邮箱的用户:
@app.get("/users/{email}")
async def get_user_by_email(email: str):
try:
user = await User.get(email=email) # 异步获取用户
return user
except DoesNotExist:
raise HTTPException(status_code=404, detail="User not found")
更新数据(Update)
更新数据也是通过异步方法完成的,下面的示例展示了如何更新用户信息:
@app.put("/users/{user_id}")
async def update_user(user_id: int, name: str, email: str):
try:
user = await User.get(id=user_id)
user.name = name
user.email = email
await user.save() # 异步保存更新后的用户数据
return {"id": user.id, "name": user.name, "email": user.email}
except DoesNotExist:
raise HTTPException(status_code=404, detail="User not found")
在这个例子中,user.save()
是一个异步操作,它将更新数据库中的用户信息,而不会阻塞其他任务。
删除数据(Delete)
删除数据的操作与更新类似,只是调用 delete()
方法。以下是一个删除用户的示例:
@app.delete("/users/{user_id}")
async def delete_user(user_id: int):
try:
user = await User.get(id=user_id)
await user.delete() # 异步删除用户
return {"detail": "User deleted successfully"}
except DoesNotExist:
raise HTTPException(status_code=404, detail="User not found")
在这个例子中,await user.delete()
是异步执行的,它将删除数据库中指定 user_id
的用户。
数据库连接池
为了更好地管理数据库连接,Tortoise ORM 提供了连接池的支持。使用连接池可以避免频繁地创建和销毁连接,从而提高性能。你可以通过在 Tortoise.init()
中配置连接池来启用这一功能:
await Tortoise.init(
db_url="postgresql://user:password@localhost:5432/dbname",
modules={"models": ["app.models"]},
_create_db=True # 创建数据库,如果不存在的话
)
# 配置连接池
await Tortoise.get_connection("default").connect()
连接池的使用使得多个数据库请求共享连接,避免了每次请求都创建新连接的性能开销。
作者:Switch616