Python Web 应用:使用 FastAPI 与 Tortoise ORM 的异步数据库操作

Python Web 应用:使用 FastAPI 与 Tortoise ORM 的异步数据库操作

目录

  1. 🛠 安装与配置 Tortoise ORM
  2. 异步数据库操作:适配 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 是一个非常简单的过程,以下是配置数据库连接的步骤:

  1. 设置数据库 URL
    首先,在 settings.py 或应用的配置文件中设置数据库连接 URL。例如,如果使用 PostgreSQL:
DATABASE_URL = "postgresql://user:password@localhost:5432/dbname"
  1. 初始化 Tortoise ORM
    然后,使用 FastAPI 的生命周期事件(例如 startupshutdown)来初始化和关闭数据库连接。在应用启动时初始化 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 是一个整型字段,标记为主键。
  • nameemail 是字符串字段,其中 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() 是异步执行的,它将从数据库中查询所有的用户并返回。由于查询是异步的,它不会阻塞其他请求的处理。

    你还可以使用 filterget 方法来查询特定条件的用户。例如,查询具有特定邮箱的用户:

    @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

    物联沃分享整理
    物联沃-IOTWORD物联网 » Python Web 应用:使用 FastAPI 与 Tortoise ORM 的异步数据库操作

    发表回复