Files
stu/dao/student_info_sql.py
T

153 lines
5.8 KiB
Python
Raw Normal View History

2026-09-22 17:13:32 +08:00
# 导入 SQLAlchemy 的 Session 类,用于类型提示
from sqlalchemy.orm import Session
# 导入学生信息模型和性别枚举
from model.student_info_region_model import Student_info, GenderEnum
# 导入完整性错误异常,用于捕获外键/唯一约束等数据库错误
from sqlalchemy.exc import IntegrityError
# ==================== 条件查询学生信息 ====================
def get_part_student_info(session: Session, student_id: str, student_name: str, gender: str):
"""
根据学号、姓名、性别查询学生信息(均为可选条件)。
:param session: 数据库会话
:param student_id: 学号,精确匹配
:param student_name: 姓名,精确匹配
:param gender: 性别,前端传“男/女”,内部转为“1/0”
:return: 学生对象列表
"""
# 前端传来的性别为 男/女,与数据库的枚举值('0'/'1')不符,需要转换
# 注意:若 gender 为 None(不筛选),此处会被错误地转为 '0',导致只查女生。
# 建议调用方在不需要筛选性别时不要传该参数,或修改此段逻辑。
if gender == '男':
gender = '1'
else:
gender = '0'
try:
# 创建基础查询
query = session.query(Student_info)
# 过滤逻辑删除:只查询未删除的记录(is_deleted = '0')
query = query.filter(Student_info.is_deleted == '0')
# 如果传入学号,则按学号精确过滤
if student_id is not None:
query = query.filter(Student_info.student_id == student_id)
# 如果传入姓名,则按姓名精确过滤
# 若需模糊查询,可将 == 改为 like(f"%{student_name}%")
if student_name is not None:
query = query.filter(Student_info.student_name == student_name)
# 如果传入性别,则按性别过滤(已转为 '0'/'1',再转为枚举)
if gender is not None:
# 把字符串转成枚举,SQLAlchemy 才能正确比较
query = query.filter(Student_info.gender == GenderEnum(gender))
# 返回所有匹配记录
return query.all()
except Exception as e:
# 出现异常直接向上抛出,由 API 层统一处理
raise e
# ==================== 添加学生信息 ====================
def add_student_info(session: Session, data: dict):
"""
新增一条学生记录。
:param session: 数据库会话
:param data: 学生信息字典,键需与模型字段对应
:return: 成功时返回字符串 '添加成功'
"""
try:
# 先检查学号是否已存在
rows = session.query(Student_info).filter(
Student_info.student_id == data['student_id']
).first()
# 如果已存在,返回 ValueError 类(注意:这里返回的是类,不是实例,也不是抛出异常)
# 调用方如果做 `if not res` 判断,ValueError 类是真值,可能导致逻辑错误。
# 建议改为 `raise ValueError("学号已存在")`
if rows is not None:
return ValueError
# 根据字典创建 ORM 对象
obj = Student_info(**data)
session.add(obj) # 加入会话
session.commit() # 提交事务,写入数据库
return '添加成功'
except Exception as e:
# 出现异常时回滚事务,避免脏数据
session.rollback()
raise e
# ==================== 修改学生信息 ====================
def update_student_info(session: Session, data: dict):
"""
根据学号更新学生信息(全量更新)。
:param session: 数据库会话
:param data: 包含 student_id 及待更新字段的字典
:return: 成功返回 '修改成功';未找到记录返回 None
"""
try:
# 使用 query.update() 批量更新,返回受影响行数
rows = session.query(Student_info).filter(
Student_info.student_id == data['student_id']
).update(data)
# 如果受影响行数为 0,说明学号不存在,无记录可更新
if rows == 0:
return None
session.commit()
return '修改成功'
except IntegrityError as e:
# 捕获数据库完整性错误(外键、唯一约束等),回滚并翻译为友好提示
session.rollback()
err_msg = str(e.orig) # 获取底层 MySQL 错误信息
if 'fk_student_region' in err_msg:
# 外键 fk_student_region 失败:region_id 在地区表中不存在
raise ValueError(
f"region_id '{data.get('region_id')}' 在地区表中不存在,请先维护 region_dimension"
)
elif 'id_card' in err_msg:
# 身份证号唯一约束冲突
raise ValueError(f"身份证号 '{data.get('id_card')}' 已被其他学生占用")
else:
# 其他完整性错误
raise ValueError(f"数据完整性错误: {err_msg}")
except Exception as e:
# 其他异常同样回滚并抛出
session.rollback()
raise e
# ==================== 删除学生信息(逻辑删除) ====================
def delete_student_info(session: Session, student_id: str):
"""
根据学号进行逻辑删除(将 is_deleted 置为 '1')。
:param session: 数据库会话
:param student_id: 学号
:return: 成功返回 '修改成功';未找到记录返回 None
"""
try:
# 使用 update 将 is_deleted 改为 '1',实现逻辑删除
rows = session.query(Student_info).filter(
Student_info.student_id == student_id
).update({'is_deleted': '1'})
# 没有匹配记录,返回 None
if rows == 0:
return None
session.commit()
return '修改成功'
except Exception as e:
# 异常时回滚
session.rollback()
raise e