106 lines
4.1 KiB
Python
106 lines
4.1 KiB
Python
# dao/teachers_dao.py
|
||
# 老师表的数据访问层(沿用原 teacher 模块风格,修复原代码中 Classinfo 引用不一致的问题)
|
||
from typing import Optional, Tuple
|
||
|
||
from sqlalchemy.orm import Session
|
||
|
||
from model.teachers import Teacher
|
||
from model.classes import Classinfo
|
||
from scheme.teachers import TeacherAdd, TeacherUpdate
|
||
|
||
|
||
class TeacherDAO:
|
||
@staticmethod
|
||
def inspect_teacher_id_unq(db: Session, teacher_id: int) -> Optional[Teacher]:
|
||
"""
|
||
根据教师ID获取教师对象(用于主键唯一性检查,查询结果包含被软删除的对象)
|
||
"""
|
||
return db.query(Teacher).filter(Teacher.teacher_id == teacher_id).first()
|
||
|
||
@staticmethod
|
||
def inspect_class_id_unq(db: Session, class_id: int) -> Optional[Classinfo]:
|
||
"""
|
||
根据班级ID获取班级对象(用于外键检查,排除被软删除对象)
|
||
"""
|
||
return (
|
||
db.query(Classinfo)
|
||
.filter(Classinfo.class_id == class_id, Classinfo.is_deleted == 0)
|
||
.first()
|
||
)
|
||
|
||
@staticmethod
|
||
def next_teacher_id(db: Session) -> int:
|
||
"""生成自增教师ID(max + 1,保证逻辑删除后不复用旧 ID)"""
|
||
max_id = db.query(Teacher.teacher_id).order_by(Teacher.teacher_id.desc()).first()
|
||
return (max_id[0] + 1) if max_id else 1
|
||
|
||
@staticmethod
|
||
def add_teacher(db: Session, teacher_data: TeacherAdd) -> Teacher:
|
||
"""新增教师;teacher_id 不传则自动生成"""
|
||
data = teacher_data.model_dump(exclude_none=True)
|
||
data.pop("is_deleted", None)
|
||
if "teacher_id" not in data:
|
||
data["teacher_id"] = TeacherDAO.next_teacher_id(db)
|
||
db_teacher = Teacher(**data)
|
||
db.add(db_teacher)
|
||
db.commit()
|
||
db.refresh(db_teacher)
|
||
return db_teacher
|
||
|
||
@staticmethod
|
||
def delete_light(db: Session, teacher_id: int) -> bool:
|
||
"""
|
||
删除教师(逻辑删除)
|
||
:return: True 删除成功 / False 不存在或已被软删除
|
||
"""
|
||
db_teacher = TeacherDAO.inspect_teacher_id_unq(db, teacher_id)
|
||
if (not db_teacher) or db_teacher.is_deleted == 1:
|
||
return False
|
||
db_teacher.is_deleted = 1
|
||
db.commit()
|
||
return True
|
||
|
||
@staticmethod
|
||
def update(db: Session, teacher_id: int, teacher_data: TeacherUpdate) -> Optional[Teacher]:
|
||
"""更新教师信息(只更新传入的非 None 字段)"""
|
||
db_teacher = TeacherDAO.inspect_teacher_id_unq(db, teacher_id)
|
||
if (not db_teacher) or db_teacher.is_deleted == 1:
|
||
return None
|
||
for key, value in teacher_data.model_dump(exclude_unset=True, exclude_none=True).items():
|
||
setattr(db_teacher, key, value)
|
||
db.commit()
|
||
db.refresh(db_teacher)
|
||
return db_teacher
|
||
|
||
@staticmethod
|
||
def get_all(db: Session, skip: int = 0, limit: int = 100) -> Tuple[int, list]:
|
||
"""分页获取所有教师(不含软删除),联表带出班级名称,返回 (总数, 列表)"""
|
||
query = (
|
||
db.query(Teacher, Classinfo.class_name)
|
||
.join(Classinfo, Teacher.class_id == Classinfo.class_id, isouter=True)
|
||
.filter(Teacher.is_deleted == 0)
|
||
)
|
||
total = query.count()
|
||
rows = query.order_by(Teacher.teacher_id).offset(skip).limit(limit).all()
|
||
# 把 class_name 附加到对象上,供响应模型 from_attributes 读取
|
||
items = []
|
||
for teacher, class_name in rows:
|
||
teacher.class_name = class_name
|
||
items.append(teacher)
|
||
return total, items
|
||
|
||
@staticmethod
|
||
def get_by_id(db: Session, teacher_id: int) -> Optional[Teacher]:
|
||
"""根据 ID 查询单个教师(不含软删除),联表带出班级名称"""
|
||
row = (
|
||
db.query(Teacher, Classinfo.class_name)
|
||
.join(Classinfo, Teacher.class_id == Classinfo.class_id, isouter=True)
|
||
.filter(Teacher.teacher_id == teacher_id, Teacher.is_deleted == 0)
|
||
.first()
|
||
)
|
||
if row is None:
|
||
return None
|
||
teacher, class_name = row
|
||
teacher.class_name = class_name
|
||
return teacher
|