今天,我们一起探讨一下fastapi的增删改查逻辑实现
ORM数据库增删改查操作
需要导入的包
from pydantic import BaseModel
from typing import Union,List
#保存数据到数据库,对用户输入数据进行校验 class StudentIn(BaseModel): name: str pwd: str sno: int clas_id: int courses: List[int] = []
1.添加单条记录
api接口实现
1.添加方式一
@api_student.post("/",tags=["添加学生"]) async def addStudent(stu: StudentIn): # 添加数据库操作 # 方式1 student = Student(name=stu.name, pwd=stu.pwd, sno=stu.sno, clas_id=stu.clas_id) #插入数据库动作 await student.save() print(student, dir(student)) return student
接口测试
查看数据库,数据已入库
2.添加方式二
# 方式2 student = await Student.create(name=stu.name, pwd=stu.pwd, sno=stu.sno, clas_id=stu.clas_id) print(student, dir(student))
数据库查看,添加成功
2.多对多表添加记录
由于多对多那张表,没有对应的模型类,所以一般无法通过模型类直接添加删除
需要借助学生表的多对多字段courses来处理
# 添加多对多关系记录 courses = await Course.filter(id__in=stu.courses) print("courses", courses) #添加的时候,要用*打散的方式传参 await student.courses.add(*courses) print("student", student.courses)
查看数据库
可以看到id 13 对15和16,多对多插入成功
1.一对多查询
#一对多查询 student = await Student.get(name="wangfang") #直接通过外键字段查询,班级名称 clasname = await student.clas.values('name') print("班级名称",clasname) #查询所有学生的班级名称,通过外键__字段值 students = await Student.all().values("name","clas__name") print(students)
2.多对多查询
#多对多查询,根据某个学生查询报的班名称和老师名称 student = await Student.get(name="wangfang") print(await student.courses.all().values('name','teacher__name')) #查询所有学生的课程名称和老师名称 students = await Student.all().values("name", "clas__name",'courses__name') print(students)
查询某一个学生的接口
#查看某个学生,基于路径参数 @api_student.get("/{student_id}") async def getOneStudent(student_id:int): #注意,与数据库的操作要加await student = await Student.get(id=student_id) print(student.name) return student
3.更新学生信息接口
#更新学生信息,使用put请求 @api_student.put("/student/{student_id}") async def update_student(student_id: int, student: StudentIn): #将对象转换为字典 data = student.dict(exclude_unset=True) #将courses字段排除,因为student表中没有courses字段 courses = data.pop("courses") print(data, courses) #更新用filter方法。因为filter查出来的对象有update方法 await Student.filter(id=student_id).update(**data) #设置多对多课程 courses = await Course.filter(id__in=student.courses) edit_student = await Student.get(id=student_id) #先把原来课程清空,再添加更新后的 await edit_student.courses.clear() await edit_student.courses.add(*courses) return student
先看下源数据库13号学生信息
多对多表
在接口执行更新
更新后
多对多表
4.删除学生接口
导入异常包
from fastapi.exceptions import HTTPException
该异常类可以设置响应状态码,描述信息等
@api_student.delete("/student/{student_id}") async def delete_student(student_id: int): #返回删除的数量 deleted_count = await Student.filter(id=student_id).delete() # 条件删除 #输入的id不存在删除报错 if not deleted_count: raise HTTPException(status_code=404, detail=f"Student {student_id} not found") #能正产给删除,返回空 return {}
删除对应学生的时候,也会级联删除对应的多对多表中数据
我们删除13号学生
执行删除请求
查看数据库,13号学生已被删除
查看多对多表13号也被删除
完整代码:
from fastapi import Request from fastapi.exceptions import HTTPException #导入模板的包 from fastapi.templating import Jinja2Templates # 实例化Jinja2对象,并将文件夹路径设置为以templates命名的文件夹 templates = Jinja2Templates(directory="templates") from pydantic import BaseModel from typing import Union,List #导入models from models import * from fastapi import APIRouter api_student = APIRouter() #保存数据到数据库,对用户输入数据进行校验 class StudentIn(BaseModel): name: str pwd: str sno: int clas_id: int courses: List[int] = [] #查看所有学生 @api_student.get("/") async def getAllStudent(): #注意,与数据库的操作要加await,得到的是queryset类型数据,[Student(),Student(),Student()....] # students = await Student.all() # print('students',students,type(students)) # # #循环打印 # for stu in students: # print(stu.name, stu.sno) #过滤查询,查询指定内容filter,得到的依然是list类型数据 # student = await Student.filter(name='liuxin') # print(student,type(student)) # #得到具体数据 # print(student[0].name) #get方法 # student = await Student.get(name="wangfang") # print(student,type(student)) # print(student.name,student.sno) #模糊查询,查询学号大于2001的学生 # students = await Student.filter(sno__gt=2001) #查询学号是2001和2002的学生 # students = await Student.filter(sno__in=[2001,2002]) # print(students) #values查询,只查出指定字段数据 # students = await Student.filter(sno__range=[1, 10000]).values('name','sno') # print(students) # for stu in students: # print(stu) #一对多查询 # student = await Student.get(name="wangfang") # # #直接通过外键字段查询,班级名称 # clasname = await student.clas.values('name') # print("班级名称",clasname) # # #查询所有学生的班级名称,通过外键__字段值 # students = await Student.all().values("name","clas__name") # print(students) #多对多查询,根据某个学生查询报的班名称和老师名称 student = await Student.get(name="wangfang") print(await student.courses.all().values('name','teacher__name')) #查询所有学生的课程名称和老师名称 students = await Student.all().values("name", "clas__name",'courses__name') print(students) return students #将学生信息显示到页面 @api_student.get("/index") async def show_student(request:Request): students = await Student.all() return templates.TemplateResponse( 'index.html', #第一个参数放模板文件 { 'request': request, # 注意,返回模板响应时,必须有request键值对,且值为Request请求对象 'students':students }, #context上下文对象,是个字典 ) #查看某个学生,基于路径参数 @api_student.get("/{student_id}") async def getOneStudent(student_id:int): #注意,与数据库的操作要加await student = await Student.get(id=student_id) print(student.name) return student #更新学生信息,使用put请求 @api_student.put("/student/{student_id}") async def update_student(student_id: int, student: StudentIn): #将对象转换为字典 data = student.dict(exclude_unset=True) #将courses字段排除,因为student表中没有courses字段 courses = data.pop("courses") print(data, courses) #更新用filter方法。因为filter查出来的对象有update方法 await Student.filter(id=student_id).update(**data) #设置多对多课程 courses = await Course.filter(id__in=student.courses) edit_student = await Student.get(id=student_id) #先把原来课程清空,再添加更新后的 await edit_student.courses.clear() await edit_student.courses.add(*courses) return student @api_student.delete("/student/{student_id}") async def delete_student(student_id: int): #返回删除的数量 deleted_count = await Student.filter(id=student_id).delete() # 条件删除 #输入的id不存在删除报错 if not deleted_count: raise HTTPException(status_code=404, detail=f"Student {student_id} not found") #能正产给删除,返回空 return {} @api_student.post("/",tags=["添加学生"]) async def addStudent(stu: StudentIn): # 添加数据库操作 # 方式1 # student = Student(name=stu.name, pwd=stu.pwd, sno=stu.sno, clas_id=stu.clas_id) # #插入数据库动作 # await student.save() # print(student, dir(student)) # 方式2 student = await Student.create(name=stu.name, pwd=stu.pwd, sno=stu.sno, clas_id=stu.clas_id) print(student, dir(student)) # 添加多对多关系记录 courses = await Course.filter(id__in=stu.courses) print("courses", courses) #添加的时候,要用*打散的方式传参 await student.courses.add(*courses) print("student", student.courses) return courses