使用Tortoise-ORM和FastAPI构建评论系统

打印 上一主题 下一主题

主题 1769|帖子 1769|积分 5307

title: 使用Tortoise-ORM和FastAPI构建评论系统
date: 2025/04/25 21:37:36
updated: 2025/04/25 21:37:36
author: cmdragon
excerpt:
在models.py中定义了Comment模子,包罗id、content、created_at、updated_at字段,并与User和Article模子建立外键关系。schemas.py中定义了CommentBase、CommentCreate、CommentUpdate和CommentResponse等Pydantic模子,用于数据验证和响应。路由层实现了创建、获取和删除评论的API,使用get_or_none处理不存在的评论,并捕获异常。测试接口通过requests举行创建和异常测试。常见报错包括外键约束失败、验证错误和事件循环未关闭,需检查外键值、哀求体匹配和正确关闭事件循环。
categories:
tags:

  • Tortoise-ORM
  • Pydantic
  • FastAPI
  • 评论系统
  • 数据库模子
  • 数据验证
  • 接口测试
扫描二维码关注大概微信搜一搜:编程智域 前端至全栈交流与发展
探索数千个预构建的 AI 应用,开启你的下一个巨大创意https://tools.cmdragon.cn/
一、Tortoise-ORM模子定义

我们起首在models.py中定义评论模子:
  1. from tortoise.models import Model
  2. from tortoise import fields
  3. class Comment(Model):
  4.     id = fields.IntField(pk=True)
  5.     content = fields.TextField()
  6.     created_at = fields.DatetimeField(auto_now_add=True)
  7.     updated_at = fields.DatetimeField(auto_now=True)
  8.     # 外键关系
  9.     user = fields.ForeignKeyField('models.User', related_name='comments')
  10.     article = fields.ForeignKeyField('models.Article', related_name='comments')
  11.     class Meta:
  12.         table = "comments"
  13.         indexes = ("created_at", "user_id", "article_id")
  14.     def __str__(self):
  15.         return f"Comment {self.id} by {self.user.username}"
复制代码
代码解析:

  • auto_now_add会在创建时自动记录时间
  • 通过related_name建立双向关联查询路径
  • 复合索引提升常用查询条件的效率
  • 继承Model基类获得ORM本领
二、Pydantic模子定义

在schemas.py中定义数据验证模子:
  1. from pydantic import BaseModel
  2. from datetime import datetime
  3. class CommentBase(BaseModel):
  4.     content: str
  5.     user_id: int
  6.     article_id: int
  7. class CommentCreate(CommentBase):
  8.     pass
  9. class CommentUpdate(BaseModel):
  10.     content: str
  11. class CommentResponse(CommentBase):
  12.     id: int
  13.     created_at: datetime
  14.     updated_at: datetime
  15.     class Config:
  16.         orm_mode = True
复制代码
验证要点:

  • 创建模子继承自基础模子
  • 更新模子仅允许修改内容字段
  • 响应模子启用orm_mode以兼容ORM对象
  • 时间字段自动转换时间格式
三、路由层实现

核心路由实现在comments.py中:
  1. from fastapi import APIRouter, Depends, HTTPException
  2. from .models import Comment
  3. from .schemas import CommentCreate, CommentResponse
  4. router = APIRouter(prefix="/comments", tags=["comments"])
  5. @router.post("/", response_model=CommentResponse)
  6. async def create_comment(comment: CommentCreate):
  7.     try:
  8.         comment_obj = await Comment.create(**comment.dict())
  9.         return await CommentResponse.from_tortoise_orm(comment_obj)
  10.     except Exception as e:
  11.         raise HTTPException(
  12.             status_code=400,
  13.             detail=f"创建评论失败: {str(e)}"
  14.         )
  15. @router.get("/{comment_id}", response_model=CommentResponse)
  16. async def get_comment(comment_id: int):
  17.     comment = await Comment.get_or_none(id=comment_id)
  18.     if not comment:
  19.         raise HTTPException(status_code=404, detail="评论不存在")
  20.     return comment
  21. @router.delete("/{comment_id}")
  22. async def delete_comment(comment_id: int):
  23.     deleted_count = await Comment.filter(id=comment_id).delete()
  24.     if not deleted_count:
  25.         raise HTTPException(status_code=404, detail="评论不存在")
  26.     return {"message": "评论删除成功"}
复制代码
技术要点:

  • 使用get_or_none替换get制止直接抛出异常
  • 批量删除返回影响行数作为判断依据
  • 异常处理覆盖数据库操作的各种失败场景
四、测试接口

使用requests测试接口:
  1. import requests
  2. BASE_URL = "http://localhost:8000/comments"
  3. # 创建测试
  4. def test_create_comment():
  5.     data = {
  6.         "content": "优质技术文章!",
  7.         "user_id": 1,
  8.         "article_id": 1
  9.     }
  10.     response = requests.post(BASE_URL, json=data)
  11.     assert response.status_code == 200
  12.     print(response.json())
  13. # 异常测试
  14. def test_invalid_user():
  15.     data = {
  16.         "content": "错误测试",
  17.         "user_id": 999,
  18.         "article_id": 1
  19.     }
  20.     response = requests.post(BASE_URL, json=data)
  21.     assert response.status_code == 400
  22.     print(response.json())
复制代码
五、课后Quiz


  • 当查询不存在的评论ID时,应该返回什么HTTP状态码?
    A) 200
    B) 404
    C) 500
    D) 400
答案:B) 404。get_or_none方法会返回None,触发自定义的404异常

  • 如何实现评论的软删除功能?
    A) 直接删除数据库记录
    B) 添加is_deleted字段
    C) 使用数据库回收站功能
    D) 修改内容为"已删除"
答案:B) 添加布尔型is_deleted字段,查询时过滤已删除的记录
六、常见报错处理


  • 报错:tortoise.exceptions.IntegrityError: FOREIGN KEY constraint failed
    缘故原由:实验关联不存在的用户或文章ID
    解决:检查外键值是否存在,添加数据库约束
  • 报错:pydantic.error_wrappers.ValidationError
    缘故原由:哀求体缺少必填字段或字段类型错误
    解决:检查哀求体是否匹配schema定义,使用try-except捕获验证错误
  • 报错:RuntimeError: Event loop is closed
    缘故原由:异步操作未正确关闭
    解决:在main.py中添加关闭事件循环的hook:
  1. from fastapi import FastAPI
  2. from tortoise.contrib.fastapi import register_tortoise
  3. app = FastAPI()
  4. register_tortoise(
  5.     app,
  6.     db_url="sqlite://db.sqlite3",
  7.     modules={"models": ["app.models"]},
  8.     generate_schemas=True,
  9.     add_exception_handlers=True,
  10. )
复制代码
余下文章内容请点击跳转至 个人博客页面 大概 扫码关注大概微信搜一搜:编程智域 前端至全栈交流与发展,阅读完整的文章:使用Tortoise-ORM和FastAPI构建评论系统 | cmdragon's Blog
往期文章归档:


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

熊熊出没

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表