From 5c70b69a5d63c7beed89845c08f0accbbc08a672 Mon Sep 17 00:00:00 2001 From: wolin_ck666_999 Date: Tue, 22 Sep 2026 13:16:32 +0800 Subject: [PATCH 1/5] =?UTF-8?q?=E4=B8=8A=E4=BC=A0=E6=96=87=E4=BB=B6?= =?UTF-8?q?=E8=87=B3=E3=80=8Capi=E3=80=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From 28b1af4f97a558bbf810e49a19b2e80ca92569aa Mon Sep 17 00:00:00 2001 From: wolin_ck666_999 Date: Tue, 22 Sep 2026 13:17:28 +0800 Subject: [PATCH 2/5] =?UTF-8?q?=E4=B8=8A=E4=BC=A0=E6=96=87=E4=BB=B6?= =?UTF-8?q?=E8=87=B3=E3=80=8Capi=E3=80=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/student_api.py | 168 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 168 insertions(+) create mode 100644 api/student_api.py diff --git a/api/student_api.py b/api/student_api.py new file mode 100644 index 0000000..f47a83d --- /dev/null +++ b/api/student_api.py @@ -0,0 +1,168 @@ +from fastapi import APIRouter, Depends, HTTPException +from sqlalchemy.orm import Session +from database import get_db +from dao.student_dao import create_student, get_student_by_id, get_student_list, update_student, delete_student_logic +from schema.student_schema import ( + StudentCreateRequest, + StudentUpdateRequest, + StudentQuery, + StudentResponse, + StudentPageResponse +) + +# 创建路由对象 API Router1 +router = APIRouter( tags=["学生管理模块"]) +@router.post("/", response_model=StudentResponse,summary="新增学生") +def add_student( + student_req: StudentCreateRequest, + db: Session = Depends(get_db) +): + db_stu = create_student(db, student_req) + # 手动转字典:model的stu_id映射响应体的id + stu_dict = { + "id": db_stu.id, + "stu_id": db_stu.stu_id, + "class_id": db_stu.class_id, + "stu_name": db_stu.stu_name, + "native_place": db_stu.native_place, + "graduate_school": db_stu.graduate_school, + "major": db_stu.major, + "enroll_date": db_stu.enroll_date, + "graduate_date": db_stu.graduate_date, + "education": db_stu.education, + "advisor_no": db_stu.advisor_no, + "age": db_stu.age, + "gender": db_stu.gender, + "is_deleted": db_stu.is_deleted + } + return StudentResponse(**stu_dict) + + +@router.get("/", response_model=StudentPageResponse,summary="根据学号姓名班级查询") +def get_student_page( + query: StudentQuery = Depends(), + db: Session = Depends(get_db) +): + + total, db_stu_list = get_student_list( + db, + stu_id=query.stu_id, + stu_name=query.stu_name, + class_id=query.class_id, + page=query.page, + page_size=query.page_size + ) + item_list = [] + for db_stu in db_stu_list: + stu_dict = { + "id": db_stu.id, + "stu_id": db_stu.stu_id, + "class_id": db_stu.class_id, + "stu_name": db_stu.stu_name, + "native_place": db_stu.native_place, + "graduate_school": db_stu.graduate_school, + "major": db_stu.major, + "enroll_date": db_stu.enroll_date, + "graduate_date": db_stu.graduate_date, + "education": db_stu.education, + "advisor_no": db_stu.advisor_no, + "age": db_stu.age, + "gender": db_stu.gender, + "is_deleted": db_stu.is_deleted + } + item_list.append(StudentResponse(**stu_dict)) + + return StudentPageResponse( + total=total, + page=query.page, + page_size=query.page_size, + items=item_list + ) + + +@router.get("/{stu_id}", response_model=StudentResponse,summary="根据id查询") +def get_one_student( + stu_id: int, + db: Session = Depends(get_db) +): + #根据主键stu_id查询单个学生 + db_stu = get_student_by_id(db, stu_id) + if db_stu is None: + raise HTTPException(status_code=404, detail="该学生不存在") + + stu_dict = { + "id": db_stu.id, + "stu_id": db_stu.stu_id, + "class_id": db_stu.class_id, + "stu_name": db_stu.stu_name, + "native_place": db_stu.native_place, + "graduate_school": db_stu.graduate_school, + "major": db_stu.major, + "enroll_date": db_stu.enroll_date, + "graduate_date": db_stu.graduate_date, + "education": db_stu.education, + "advisor_no": db_stu.advisor_no, + "age": db_stu.age, + "gender": db_stu.gender, + "is_deleted": db_stu.is_deleted + } + return StudentResponse(**stu_dict) + + +@router.put("/{stu_id}", response_model=StudentResponse,summary="修改学生信息") +def edit_student( + stu_id: int, + update_req: StudentUpdateRequest, + db: Session = Depends(get_db) +): + #修改学生信息 + db_stu = update_student(db, stu_id, update_req) + if db_stu is None: + raise HTTPException(status_code=404, detail="该学生不存在") + + stu_dict = { + "id": db_stu.id, + "stu_id": db_stu.stu_id, + "class_id": db_stu.class_id, + "stu_name": db_stu.stu_name, + "native_place": db_stu.native_place, + "graduate_school": db_stu.graduate_school, + "major": db_stu.major, + "enroll_date": db_stu.enroll_date, + "graduate_date": db_stu.graduate_date, + "education": db_stu.education, + "advisor_no": db_stu.advisor_no, + "age": db_stu.age, + "gender": db_stu.gender, + "is_deleted": db_stu.is_deleted + } + return StudentResponse(**stu_dict) + + +@router.delete("/{stu_id}", response_model=StudentResponse,summary="删除学生信息") +def remove_student( + stu_id: int, + db: Session = Depends(get_db) +): + #逻辑删除学生 + db_stu = delete_student_logic(db, stu_id) + if db_stu is None: + raise HTTPException(status_code=404, detail="该学生不存在") + + stu_dict = { + "id": db_stu.id, + "stu_id": db_stu.stu_id, + "stu_name": db_stu.stu_name, + "class_id": db_stu.class_id, + "native_place": db_stu.native_place, + "graduate_school": db_stu.graduate_school, + "major": db_stu.major, + "enroll_date": db_stu.enroll_date, + "graduate_date": db_stu.graduate_date, + "education": db_stu.education, + "advisor_no": db_stu.advisor_no, + "age": db_stu.age, + "gender": db_stu.gender, + "is_deleted": db_stu.is_deleted + } + return StudentResponse(**stu_dict) From 1e891a73e1e8f2488c1ccbe389debf02e677001f Mon Sep 17 00:00:00 2001 From: wolin_ck666_999 Date: Tue, 22 Sep 2026 13:17:44 +0800 Subject: [PATCH 3/5] =?UTF-8?q?=E4=B8=8A=E4=BC=A0=E6=96=87=E4=BB=B6?= =?UTF-8?q?=E8=87=B3=E3=80=8Cdao=E3=80=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dao/student_dao.py | 57 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 dao/student_dao.py diff --git a/dao/student_dao.py b/dao/student_dao.py new file mode 100644 index 0000000..366ad79 --- /dev/null +++ b/dao/student_dao.py @@ -0,0 +1,57 @@ +from sqlalchemy.orm import Session +from model.student_model import Student +from schema.student_schema import StudentCreateRequest,StudentUpdateRequest +def create_student(db: Session, student_create: StudentCreateRequest): + """ + 新增学生 + : db: 数据库会话 + :student_c reate: 前端传来的新增请求体 + """ + db_student = Student(**student_create.model_dump())#请求体转为字典,再解包创建实体对象 + db.add(db_student)#添加 + db.commit()#提交事务 + new_student=db.query(Student).filter( + Student.stu_id==student_create.stu_id, + Student.is_deleted==False).first() + #查询 Student 表,取第一条,没有则返回 None + return new_student +def get_student_by_id(db: Session, stu_id: int):#根据stu_id查询单个学生 + query = db.query(Student).filter( + Student.stu_id == stu_id, + Student.is_deleted == False) + return query.first() +def get_student_list(db: Session, stu_id:None, + class_id:str=None, page:int=1, page_size:int=10, stu_name:str=None):#查询学生列表,支持按照编号/姓名/班级删选 + # 基础查询:只查未逻辑删除的学生 + query = db.query(Student).filter(Student.is_deleted == False) + if stu_id: + query = query.filter(Student.stu_id == stu_id) + if stu_name: + query = query.filter(Student.stu_name == stu_name) + if class_id: + query = query.filter(Student.class_id == class_id) + total = query.count()#统计满足条件的记录 + offset = (page - 1) * page_size# 计算分页偏移量:跳过前面 (page-1)*page_size 条 + db_student_list = query.offset(offset).limit(page_size).all()# 执行分页查询:跳过offset条,取page_size条 + return total, db_student_list +def update_student(db: Session, stu_id:int,student_update: StudentUpdateRequest): + """修改学生信息 +db: 数据库会话stu_id: 要修改的学生主键student_update: 前端传来的修改请求体: +""" + db_student = get_student_by_id(db=db,stu_id=stu_id) + if not db_student: + return None#先查学生,查不到报错 + update_data=student_update.model_dump(exclude_unset=True)#只解析前端输入的键值对,默认值不会解析 + for k,v in update_data.items(): + setattr(db_student,k,v)#把 value 赋给 db_student 的 key 属性。 + db.commit() + updated_student=get_student_by_id(db, stu_id) + return updated_student +def delete_student_logic(db: Session, stu_id:int): + db_student = get_student_by_id(db, stu_id) + if not db_student: + return None + db_student.is_deleted = True#把逻辑删除标记改成True + db.commit()#重新查询,返回标记已删除的这条记录 + deleted_student = db.query(Student).filter(Student.stu_id == stu_id).first() + return deleted_student From dbc12e39226e520253e450779fe20b17adbcbad5 Mon Sep 17 00:00:00 2001 From: wolin_ck666_999 Date: Tue, 22 Sep 2026 13:18:08 +0800 Subject: [PATCH 4/5] =?UTF-8?q?=E4=B8=8A=E4=BC=A0=E6=96=87=E4=BB=B6?= =?UTF-8?q?=E8=87=B3=E3=80=8Cmodel=E3=80=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- model/student_model.py | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 model/student_model.py diff --git a/model/student_model.py b/model/student_model.py new file mode 100644 index 0000000..9b2c8bf --- /dev/null +++ b/model/student_model.py @@ -0,0 +1,25 @@ +from database import Base +from sqlalchemy import Column,Integer,String,Date,Boolean, Enum as SQLEnum +from enum import Enum +class Sex(Enum): + m= "男" + w= "女" +class Student(Base): + __tablename__ = 's_student' + id=Column(Integer, primary_key=True,autoincrement=True,comment="数据库主键id") + stu_id=Column(String(50),unique=True,nullable=False,comment='学生id') + class_id=Column(String(50),#ForeignKey=("s_class.class_id"), + comment='学生班级') + stu_name=Column(String(30),nullable=False,comment='学生姓名') + native_place = Column(String(100), comment="籍贯") + graduate_school = Column(String(100), comment="毕业院校") + major = Column(String(50), comment="专业") + enroll_date = Column(Date, comment="入学时间") + graduate_date = Column(Date, comment="毕业时间") + education = Column(String(30), comment="学历") + advisor_no = Column(String(50), comment="顾问编号") + age = Column(Integer, comment="年龄") + gender = Column( + SQLEnum(Sex, values_callable=lambda x: [e.value for e in x]), + comment="性 别") + is_deleted = Column(Boolean, default=False, comment="逻辑删除标记:False未删除,True已删除") \ No newline at end of file From ad5cd8dc9104c27eebeee466c63c99c5f69b1469 Mon Sep 17 00:00:00 2001 From: wolin_ck666_999 Date: Tue, 22 Sep 2026 13:18:30 +0800 Subject: [PATCH 5/5] =?UTF-8?q?=E4=B8=8A=E4=BC=A0=E6=96=87=E4=BB=B6?= =?UTF-8?q?=E8=87=B3=E3=80=8Cschema=E3=80=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- schema/student_schema.py | 58 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 schema/student_schema.py diff --git a/schema/student_schema.py b/schema/student_schema.py new file mode 100644 index 0000000..c892209 --- /dev/null +++ b/schema/student_schema.py @@ -0,0 +1,58 @@ +from typing import Optional,List +from pydantic import BaseModel,Field +from datetime import date +from model.student_model import Sex +##================ =====请求体=============== +class StudentCreateRequest(BaseModel): + stu_id:str=Field(...,description="学生id") + class_id:Optional[str]=Field(None,description="学生班级id") + stu_name: str = Field(..., description="学生姓名") + native_place: Optional[str] = Field(None, description="籍贯") + graduate_school: Optional[str] = Field(None, description="毕业院校") + major: Optional[str] = Field(None, description="专业") + enroll_date: Optional[date] = Field(None, description="入学时间") + graduate_date: Optional[date] = Field(None, description="毕业时间") + education: Optional[str] = Field(None, description="学历") + advisor_no: Optional[str] = Field(None, description="顾问编号") + age: Optional[int] = Field(None, ge=0, description="年龄,不能负数") + gender: Optional[Sex] = Field(None, description="性别") +class StudentUpdateRequest(BaseModel): + stu_id:Optional[str]=None#学生id + class_id: Optional[str] = None # 学生班级 + stu_name: Optional[str] = None # 学生姓名 + native_place: Optional[str] = None # 籍贯 + graduate_school: Optional[str] = None # 毕业院校 + major: Optional[str] = None # 专业 + enroll_date: Optional[date] = None # 入学时间 + graduate_date: Optional[date] = None # 毕业时间 + education: Optional[str] = None # 学历 + advisor_no: Optional[str] = None # 顾问编号 + age: Optional[int] = Field(None, ge=0) # 年龄,不能负数 + gender: Optional[Sex] = Field(None, description="性别") # 性别''' +class StudentQuery(BaseModel): + stu_id: Optional[str] = None # 学生编号筛选 + stu_name: Optional[str] = None # 学生姓名筛选 + class_id: Optional[str] = None # 班级筛选 + page: int = Field(1, ge=1, description="页码,默认第1页") + page_size: int = Field(10, ge=1, le=100, description="每页条数,默认10条") +##=====================响应体=============== +class StudentResponse(BaseModel): + stu_id: str# 学生编号 + class_id: Optional[str]# 学生班级 + stu_name: str# 学生姓名 + native_place: Optional[str] # 籍贯 + graduate_school: Optional[str] # 毕业院校 + major: Optional[str]# 专业 + enroll_date: Optional[date] # 入学时间 + graduate_date: Optional[date] # 毕业时间 + education: Optional[str] # 学历 + advisor_no: Optional[str]# 顾问编号 + age: Optional[int]# 年龄 + gender: Optional[Sex] = Field(None, description="性别")# 性别 + is_deleted: bool# 逻辑删除标记 +# 分页列表响应体:查询学生列表时返回 +class StudentPageResponse(BaseModel): + total: int# 符合条件的总记录数 + page: int# 当前页码 + page_size: int# 每页数据条数 + items: List[StudentResponse] # 当前页学生数据列表 \ No newline at end of file