在现代 Web 开发中,选择合适的框架和工具对构建高效的应用至关重要。FastAPI 作为一个快速、现代的 Web 框架,以其异步特性和对 Python 类型提示的支持而备受欢迎。而 Tortoise ORM 则是一个适用于异步应用的轻量级 ORM,特别适合与 FastAPI 结合使用。本文将通过使用 SQLite 数据库,手把手教你如何在 FastAPI 项目中集成 Tortoise ORM,从而实现高效的异步数据库操作。
项目结构
在深入代码实现之前,我们首先规划一下项目的目录结构。这有助于我们更有条理地组织代码。
fastapi_tortoise/
├── app/
│ ├── __init__.py
│ ├── main.py
│ ├── models.py
│ └── routes/
│ ├── __init__.py
│ └── users.py
├── database.py
└── tortoise_config.py
这样的结构将我们的项目分为几个模块:app
用于存放主要的应用逻辑,database.py
用于数据库相关的初始化和连接,tortoise_config.py
则是 Tortoise ORM 的配置文件。
安装和配置
在开始编写代码之前,我们需要先安装必要的库。确保你的 Python 环境中已经安装了 FastAPI 和 Uvicorn:
pip install fastapi uvicorn
接下来,安装 Tortoise ORM 及其 SQLite 驱动:
pip install tortoise-orm aiosqlite
配置 Tortoise ORM
在 tortoise_config.py
文件中,配置 Tortoise ORM 来连接 SQLite 数据库。
# tortoise_config.py
TORTOISE_ORM = {"connections": {"default": "sqlite://db.sqlite3"},"apps": {"models": {"models": ["app.models", "aerich.models"],"default_connection": "default",},},
}
这里,我们定义了一个默认的数据库连接,使用 SQLite 作为存储后端,数据库文件名为 db.sqlite3
。
数据库初始化
在 database.py
文件中,编写初始化和关闭 Tortoise ORM 的代码。
from tortoise import Tortoise, run_asyncasync def init():await Tortoise.init(config=TORTOISE_ORM)await Tortoise.generate_schemas()async def close():await Tortoise.close_connections()
定义模型
接下来,在 app/models.py
中定义我们的数据库模型。以用户模型为例:
from tortoise import fields
from tortoise.models import Modelclass User(Model):id = fields.IntField(pk=True)username = fields.CharField(max_length=50, unique=True)email = fields.CharField(max_length=128, unique=True)password_hash = fields.CharField(max_length=128)class Meta:table = 'users'def __str__(self):return self.username
安全地处理密码
在任何涉及用户密码的应用中,安全性都是至关重要的。我们不能将明文密码直接存储在数据库中,而是应该使用哈希函数进行加密。
我们可以使用 passlib
库来处理密码哈希:
pip install passlib[bcrypt]
在 app/models.py
中定义一个函数来生成密码哈希:
from passlib.context import CryptContextpwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")def get_password_hash(password: str) -> str:return pwd_context.hash(password)
定义 API 路由
在 app/routes/users.py
中,定义用户相关的 API 路由,包括创建、读取、更新和删除用户。
from fastapi import APIRouter, HTTPException
from app.models import User
from pydantic import BaseModel, EmailStrrouter = APIRouter()class UserIn(BaseModel):username: stremail: EmailStrpassword: strclass UserOut(BaseModel):id: intusername: stremail: strclass Config:orm_mode = True@router.post("/", response_model=UserOut)
async def create_user(user_in: UserIn):hashed_password = get_password_hash(user_in.password)user = await User.create(username=user_in.username,email=user_in.email,password_hash=hashed_password)return user@router.get("/{user_id}", response_model=UserOut)
async def get_user(user_id: int):user = await User.get_or_none(id=user_id)if not user:raise HTTPException(status_code=404, detail="User not found")return user@router.put("/{user_id}", response_model=UserOut)
async def update_user(user_id: int, user_in: UserIn):user = await User.get_or_none(id=user_id)if not user:raise HTTPException(status_code=404, detail="User not found")user.username = user_in.usernameuser.email = user_in.emailuser.password_hash = get_password_hash(user_in.password)await user.save()return user@router.delete("/{user_id}", status_code=204)
async def delete_user(user_id: int):user = await User.get_or_none(id=user_id)if not user:raise HTTPException(status_code=404, detail="User not found")await user.delete()
数据迁移
Tortoise ORM 集成了 Aerich 以便进行数据库迁移。首先,安装 Aerich:
pip install aerich
然后初始化 Aerich 并生成迁移脚本:
aerich init -t tortoise_config.TORTOISE_ORM
aerich init-db
aerich migrate
aerich upgrade
整合 FastAPI 应用
在 app/main.py
中,创建 FastAPI 应用并整合 Tortoise ORM 初始化逻辑。
from fastapi import FastAPI
from app.routes import users
import databaseapp = FastAPI()@app.on_event("startup")
async def startup_event():await database.init()@app.on_event("shutdown")
async def shutdown_event():await database.close()app.include_router(users.router, prefix="/users", tags=["users"])
运行应用
使用 Uvicorn 运行 FastAPI 应用:
uvicorn app.main:app --reload
测试 API
使用工具如 Postman 或 curl 测试 API 的各个端点。
创建用户
curl -X POST "http://127.0.0.1:8000/users/" -H "Content-Type: application/json" -d '{"username": "testuser", "email": "test@example.com", "password": "password"}'
获取用户
curl "http://127.0.0.1:8000/users/1"
更新用户
curl -X PUT "http://127.0.0.1:8000/users/1" -H "Content-Type: application/json" -d '{"username": "updateduser", "email": "updated@example.com", "password": "newpassword"}'
删除用户
curl -X DELETE "http://127.0.0.1:8000/users/1"
优化建议
-
数据库性能优化:
- 考虑为常用查询添加索引。
- 使用缓存来减少数据库查询次数。
-
安全性增强:
- 实现 JWT 身份验证。
- 确保所有输入都经过验证和消毒,以防止 SQL 注入和 XSS 攻击。
-
测试和持续集成:
- 使用
pytest
和pytest-asyncio
编写单元测试。 - 在 CI/CD 流程中自动化测试和部署。
- 使用
总结
通过本文的指导,你应该能够在 FastAPI 项目中集成 Tortoise ORM,并使用 SQLite 数据库进行异步操作。我们涵盖了从安装配置到实现完整的 CRUD 操作的各个步骤,并提供了一些优化和安全性的建议。希望这篇指南能帮助你在实际项目中更好地应用这些技术。
如果你有任何问题或建议,欢迎在评论区分享你的想法和经验!