21 Commits
Author SHA1 Message Date
lookerZz 89a10c598b update teacher models 2026-09-21 15:06:09 +08:00
lookerZz da71b48a10 Merge pull request '两个模块' (#14) from 张昕浩 into main
Reviewed-on: #14
2026-09-21 14:40:35 +08:00
lookerZz 9173db07c4 Merge pull request '南方宇' (#15) from 南方宇 into main
Reviewed-on: #15
2026-09-21 14:37:26 +08:00
lookerZz 65997d9c31 两个模块写好 2026-09-21 14:34:43 +08:00
wolin_nanfangyu_mj d28b4beff9 南方宇model合并测试 2026-09-21 14:33:43 +08:00
lookerZz ff49a4ac20 Merge pull request '2026.09.21-14:25 合并请求' (#13) from zhangyi into main
Reviewed-on: #13
2026-09-21 14:27:08 +08:00
lookerZz ae8af02d1b Merge pull request 'Wolin zk' (#11) from wolin_zk into main
Reviewed-on: #11
2026-09-21 14:26:03 +08:00
lookerZz 8a4c769269 Merge pull request 'Li yujie' (#12) from LI_YUJIE into main
Reviewed-on: #12
2026-09-21 14:25:28 +08:00
wolin_zhangyi 24fc2d8c89 1、在models.teacher.py新建
class Teacher(Base)
class ClassTeachers(Base)
2、在schemas.teacher.py定义两个请求体
class TeacherCreate(BaseModel)
class TeacherUpdate(BaseModel)
2026-09-21 14:22:43 +08:00
lookerZz ece3b235ec Merge pull request 'Zhutt' (#9) from zhutt into main
Reviewed-on: #9
2026-09-21 14:22:28 +08:00
曾凯 9f53b3389c 曾凯成绩数据库模型 2026-09-21 14:21:06 +08:00
zhutt e9e6aaa838 Merge remote-tracking branch 'origin/zhutt' into zhutt
# Conflicts:
#	models/class_model.py
2026-09-21 14:18:58 +08:00
wolin_nanfangyu_mj b898896686 南方宇model合并测试 2026-09-21 14:18:42 +08:00
zhutt 78a9f1bdcb 0921第一次修改 2026-09-21 14:17:09 +08:00
wolin_liyujie 546bc68847 写好了增加学生接口,增加学生dao层,main里加入了student——router 2026-09-21 12:36:57 +08:00
wolin_liyujie 9692c0867d Merge remote-tracking branch 'origin/main' into LI_YUJIE 2026-09-21 11:18:24 +08:00
wolin_liyujie 21317efe78 建好了学生表模型 2026-09-21 11:17:40 +08:00
zhutt 2ddd390682 0921第一次修改 2026-09-21 10:38:52 +08:00
lookerZz ebbcd3f616 Merge pull request 'model consultant.py已更新完毕' (#8) from bx into main
Reviewed-on: #8
2026-09-21 10:27:12 +08:00
zhutt 9b490cb76a 0921第一次修改 2026-09-21 10:09:30 +08:00
曾凯 c1f0283792 111 2026-09-21 09:19:15 +08:00
23 changed files with 468 additions and 188 deletions
+1
View File
@@ -5,3 +5,4 @@
test33
gesd
jhj
+25
View File
@@ -0,0 +1,25 @@
from fastapi import APIRouter,Depends,HTTPException
from schemas.class_schema import *
from core.database import get_db
from dao.class_dao import *
classes_router = APIRouter()
@classes_router.post('/',response_model=ClassResponse)
def post_classes(classes:ClassCreate,db=Depends(get_db)):
c = classes.model_dump()
r = post_classes_dao( c , db )
if r :
return ClassResponse( total=1,data=c )
else :
raise HTTPException(status_code=500,detail='添加失败,服务器繁忙,请稍后添加!')
@classes_router.put('/{id}',response_model=ClassResponse)
def put_classes(id:int,classes:ClassUpdate,db=Depends(get_db)):
updates = classes.model_dump( exclude_unset=True )
r = update_classes_dao( id , db , updates )
if r :
return ClassResponse( total=1,data=updates )
else :
raise HTTPException(status_code=500, detail='更新失败,该班级已不存在或服务器繁忙,请稍后更新!')
-63
View File
@@ -1,63 +0,0 @@
from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.orm import Session
from core.database import get_db
from schemas.consultant import ConsultantCreate, ConsultantUpdate, ConsultantResponse
from dao import consultant as dao_consultant
router = APIRouter()
@router.get(
path="/consultants",
tags=['顾问管理模块'],summary='顾问模糊分页查询')
def read_consultants(
db: Session = Depends(get_db),
page:int=1,
page_size:int=20,
name:str|None=None,
phone:str|None=None
):
return dao_consultant.get_consultant_list(db, page, page_size, name, phone)
@router.post("/consultants", response_model=ConsultantResponse,tags=['顾问管理模块'],summary='顾问增加')
def create_consultant(
obj_in: ConsultantCreate,
db: Session = Depends(get_db)
):
return dao_consultant.create_consultant(db, obj_in)
@router.get("/consultants/{id}", response_model=ConsultantResponse,tags=['顾问管理模块'],summary='顾问查询')
def read_consultant(id: int, db: Session = Depends(get_db)):
res = dao_consultant.get_consultant_by_id(db, cid=id)
if res is None:
raise HTTPException(status_code=404, detail="顾问不存在或已删除")
return res
@router.put(
path="/consultants/{id}",
response_model=ConsultantResponse,
tags=['顾问管理模块'],summary='顾问更新')
def update_consultant(
id: int,
obj_in: ConsultantUpdate,
db: Session = Depends(get_db)
):
# model_dump 排除为None的字段,只更新前端传过来的字段
update_dict = obj_in.model_dump(exclude_none=True)
res = dao_consultant.update_consultant(db, cid=id, update_data=update_dict)
if res is None:
raise HTTPException(status_code=404, detail="顾问不存在或已删除")
return res
@router.delete("/consultants/{id}", response_model=ConsultantResponse,tags=['顾问管理模块'],summary='顾问删除')
def delete_consultant(id: int, db: Session = Depends(get_db)):
res = dao_consultant.delete_consultant(db, cid=id)
if res is None:
raise HTTPException(status_code=404, detail="顾问不存在或已删除")
return res
+28
View File
@@ -0,0 +1,28 @@
from fastapi import APIRouter,HTTPException,Depends
from DoubaoTeam.core.database import get_db
from DoubaoTeam.models.student import Student
from DoubaoTeam.models.score import Score
from DoubaoTeam.dao.statistics import *
from DoubaoTeam.schemas.common import SuccessResponse
from sqlalchemy.orm import Session
statistics_router=APIRouter()
@statistics_router.get("/scores/age-over-30",response_model=SuccessResponse)
def api_age_over_thirty(db:Session=Depends(get_db)):
try:
age_over_thirty_list=age_over_thirty(Student,db)
return SuccessResponse(status_code=200,msg=age_over_thirty_list)
except NoExist as e:
raise HTTPException(status_code=404,detail=str(e))
# 这边功能函数返回的是一个字典
@statistics_router.get("/classes/gender-count",response_model=SuccessResponse)
def api_gender_count(db:Session=Depends(get_db)):
try:
result = gender_count(Student,db)
return SuccessResponse(status_code=200,msg=result)
except NoExist as e:
raise HTTPException(status_code=404,detail=str(e))
+14
View File
@@ -0,0 +1,14 @@
from fastapi import APIRouter,Depends,HTTPException
from sqlalchemy.orm import Session
from dao.student import *
from schemas.student import StudentCreate
student_router = APIRouter()
@student_router.post("/student")
def create_student(request:StudentCreate,db:Session,create = Depends(create_students)):
d = request.model_dump()
r = create_students(d,db)
if not r:
raise HTTPException(status_code=500,detail='服务器繁忙,请稍后添加!')
return {'code':200,'detail':"添加学生成功"}
+1 -1
View File
@@ -17,7 +17,7 @@ IP:localhost
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker,declarative_base
from .config import (
from core.config import (
database_connect_user,
database_connect_password,
database_connect_ip,
+29
View File
@@ -0,0 +1,29 @@
from models.class_model import Classes
def post_classes_dao( c , db ):
try :
cc = Classes( **c )
db.add( cc )
except :
db.rollback()
return False
else :
db.commit()
return True
def update_classes_dao( class_id , db , updates ):
try :
db.query( Classes ).filter( Classes.id==class_id , Classes.is_deleted==0 ) .update( updates )
except :
db.rollback()
return False
else :
db.commit()
return True
# def get_classes_dao( class_id , class_name , db ):
# try :
# r = db.query( Classes ).filter( Classes.id==class_id , Classes.is_deleted==0 ) .all()
# except :
# db.rollback()
-82
View File
@@ -1,82 +0,0 @@
from models.consultant import Consultant
from schemas.consultant import ConsultantCreate, ConsultantUpdate
from sqlalchemy.orm import Session
def create_consultant(db:Session, obj_in: ConsultantCreate):
try:
db_obj = Consultant(**obj_in.model_dump())
db.add(db_obj)
except:
db.rollback()
return False
else:
db.commit()
return db_obj
# 查询全部可分页(过滤已删除)
def get_consultant_list(
db: Session,
page: int = 1,
page_size: int = 20,
name: str | None = None,
phone: str | None = None
):
page_size = max(1, min(page_size, 100))
skip = (page - 1) * page_size
query = db.query(Consultant).filter(Consultant.is_deleted == 0)
# 有传参数才追加过滤条件
if name:
query = query.filter(Consultant.consultant_name.like(f"%{name}%"))
if phone:
query = query.filter(Consultant.phone.like(f"%{phone}%"))
total = query.count()
items = query.offset(skip).limit(page_size).all()
return {
"items": items,
"total": total,
"page": page,
"page_size": page_size
}
# 根据id查单条
def get_consultant_by_id(db:Session, cid: int):
return db.query(Consultant).filter(Consultant.id == cid, Consultant.is_deleted == 0 ).first()
# 修改
def update_consultant(db: Session, cid: int, update_data: dict):
try:
db_obj = db.query(Consultant).filter(
Consultant.id == cid,
Consultant.is_deleted == 0
).first()
if not db_obj:
return None
# 循环赋值
for k, v in update_data.items():
setattr(db_obj, k, v)
db.commit()
db.refresh(db_obj) # 刷新从数据库拿最新数据(updated_at)
return db_obj
except Exception:
db.rollback()
return None
# 逻辑删除(只改is_deleted=1)
def delete_consultant(db:Session, cid: int):
try:
db_obj = get_consultant_by_id(db, cid)
if not db_obj:
return None
db_obj.is_deleted = 1
except:
db.rollback()
return None
else:
db.commit()
return db_obj
+30
View File
@@ -0,0 +1,30 @@
from DoubaoTeam.schemas.statistics import NoExist
from sqlalchemy import func
#`GET /statistics/students/age-over-30`
#查询所有超过 30 岁的学员信息
def age_over_thirty(Student,db):
student_list=db.query(Student).filter(Student.age>=30).all()
if not student_list :
raise NoExist('无目标年龄大于30岁')
return student_list
def gender_count(Student,db):
result=db.query(Student.class_id,Student.gender,func.count(Student.id)).group_by(Student.class_id,Student.gender).all()
if not result :
raise NoExist('班里招点人吧,要倒闭了')
dict1 = {}
for i,j,k in result:
if i not in dict1 :
dict1[i]={'男':0,'女':0}
dict[i][j]+=k
return dict1
#查询每次考试成绩都在 80 分以上的学生编号、姓名和成绩
def score_over_eighty(Score,Student,db):
student_list=db.query(Student.id, Student.student_name)\
.join(Student,Score.student_id==Student.id).group_by(Student.student_no,Student.student_name)\
.having(func.min(Score.score)>80).all()
for i in student_list:
student_list2 = db.query(Student.student_no, Student.student_name,Score.score).join(Student,Score.student_id==Student.id).filter(i.id==Student.id).all()
+16
View File
@@ -0,0 +1,16 @@
from schemas.student import *
from core.database import get_db
from models.student import *
from utils.code_generator import generate_no
def create_students(d,db):
stu = Student(**d)
try:
db.add(stu)
generate_no("student_no", "STU", stu, db)
db.commit()
except:return False
else:
return True
+7 -3
View File
@@ -1,21 +1,25 @@
from fastapi import FastAPI
from api.example import example_router
from middleware import log_middleware
from api.statistics import statistics_router
import uvicorn
from api.student import student_router
app = FastAPI()
app.middleware("http")(log_middleware)
#-------------朱婷婷--------------
from api.class_api import classes_router
app.include_router(classes_router,tags=['班级接口'],prefix="/classes")
#-------------李玉杰--------------
app.include_router(student_router)
#-------------张义---------------
#-------------薄鑫---------------
from api import consultant
app.include_router(consultant.router)
#-------------张昕浩---------------
app.include_router(example_router)
app.include_router(statistics_router, prefix="/statistics")
#-------------曾凯---------------
+3 -4
View File
@@ -1,7 +1,6 @@
from sqlalchemy import *
from datetime import datetime,time,date
Base = declarative_base() # 执行函数,返回一个基类
from sqlalchemy import * # 导入sqlalchemy模块下所有的类,以便下面创建班级表模型和声明表的字段
from datetime import datetime # 导入datetime模块下的datetime类
from core.database import Base # 从core软件包下的database模块导入Base
class Classes( Base ): # 在python里的名字
__tablename__ = 'classes' # 在数据库中表的名字
+53
View File
@@ -0,0 +1,53 @@
from sqlalchemy import (Column, Integer, String, Text,
BigInteger,ForeignKey,VARCHAR,DateTime
)
from sqlalchemy.dialects.mssql import TINYINT
from core.database import Base
from datetime import datetime
#班级老师关系表 class_teachers_info_detail 中间表 ORM 模型完整定义
#字段包括id,class_id,teacher_id,role,created_at,updated_at,is_deleted
class ClassTeachers(Base):
__tablename__ = "class_teachers_info_detail"
id = Column(
BigInteger
,primary_key=True
,autoincrement=True
,comment='关系')
class_id = Column(
BigInteger
,ForeignKey('class_id')
,nullable=False
,comment='关联 class_id'
)
teacher_id = Column(
BigInteger
,ForeignKey('teacher_id')
,nullable=False
,comment='关联 teacher_id'
)
role = Column(
VARCHAR(30)
,nullable=False
,comment='老师在班级中的角色:head_teacher班主任 / lecturer授课老师 / assistant助教'
)
created_at = Column(
DateTime
,nullable=False
,default=datetime.now()
,comment='创建时间'
)
updated_at = Column(
DateTime
,nullable=False
,default=datetime.now()
,comment='更新时间'
)
is_deleted = Column(
TINYINT
,nullable=False
,default=0
,comment='逻辑删除'
)
+2 -2
View File
@@ -3,12 +3,12 @@ from sqlalchemy import *
from datetime import datetime
from core.database import Base
class Consultant(Base):
__tablename__ = "consultant_info_detail"
__tablename__ = "consultants"
id = Column(Integer, primary_key=True, autoincrement=True, comment="主键")
consultant_no = Column(String(50), unique=True, nullable=False, comment="顾问编号")
consultant_name = Column(String(50), nullable=False, comment="顾问姓名")
phone = Column(String(20), nullable=True, comment="联系电话")
phone = Column(String(11), nullable=True, comment="联系电话")
email = Column(String(100), nullable=True, comment="邮箱")
remark = Column(String(255), nullable=True, comment="备注")
+40
View File
@@ -0,0 +1,40 @@
from sqlalchemy import *
from sqlalchemy.orm import declarative_base,sessionmaker
from datetime import datetime
from core.database import Base, engine
# 为了符合三范式,就业表只保存 student_id,不保存学生姓名和班级名称。查询返回时通过关联 students 和 classes 带出学生姓名、班级名称。
class Employment(Base):
__tablename__ = "employments" # 实际数据库的表名字
id = Column(BigInteger, primary_key=True # 主键
, autoincrement=True # 声明是自增主键
,comment="就业信息主键id")
student_id = Column(BigInteger, ForeignKey("students.id") # 外键 -> students.id
, nullable=False # 不允许为null
,comment="关联学生id")
employment_status = Column(String(50)
, default="not_started"
,comment="就业状态:not_started/job_hunting/offered/employed")
employment_open_date = Column(Date
,comment="就业开放时间")
offer_date = Column(Date
,comment="offer下发时间")
company_name = Column(String(100)
, comment="就业公司名称")
salary = Column(DECIMAL(10, 2) # 高精度浮点数薪资,最多 10 位数字,小数占 2 位
, comment="就业薪资")
remark = Column(String(255)
,default=None
, comment="备注信息")
created_at = Column(DateTime
, default=datetime.now
, comment="创建时间")
updated_at = Column(DateTime
, default=datetime.now
, onupdate=datetime.now
,comment="更新时间")
is_deleted = Column(SmallInteger
,default=0
,comment="逻辑删除:0正常,1删除")
+46
View File
@@ -0,0 +1,46 @@
from sqlalchemy import *
from core.database import Base
from datetime import datetime,date
class Score(Base):
__tablename__ = "score_info_detail"
id = Column(Integer
, primary_key=True
,autoincrement=True
,comment="成绩表序号,自增主键"
)
student_id = Column(Integer
,ForeignKey("student.id")
,nullable=False
,comment="学生学号"
)
score = Column(DECIMAL(4,1)
,CheckConstraint("score between 0 and 100")
)
exam_seq= Column(Integer
, nullable=False
,comment="考试序次")
__table_args__ = (
UniqueConstraint("student_id"
, "exam_seq"
, name="uk_student_exam_seq"),
)#学生id和学生姓名应为联合唯一,即一个学生一次考试只能有一个分数
exam_date=Column(Date
,default=date.today
,comment="考试日期"
)
created_at=Column(DateTime
,default=datetime.now
,comment="创建时间"
)
updated_at=Column(DateTime
,default=datetime.now
,onupdate=datetime.now
,comment="更新时间"
)
remark=Column(String(225)
,comment="备注说明"
)
is_deleted=Column(Integer
,default=0
,comment="逻辑删除标记:未删除0,已删除1"
)
+45
View File
@@ -0,0 +1,45 @@
from core.database import Base
from sqlalchemy import *
from datetime import datetime
class Student(Base):
__tablename__ = 'student_info_detail'
id = Column(Integer
, primary_key=True
, autoincrement=True
, comment = '学生编号,自增主键'
)
student_no = Column(VARCHAR(50)
, unique = True)
student_name = Column(VARCHAR(50))
class_id = Column(Integer
,foreign_key = 'class_info_detail.id'
)#外键约束 班级表的主键id,存在这个班级,学生表才可以输入
consultant_id = Column(Integer
,nullable = True
,foreign_key = 'consultant_info_detail.id'
)#外键约束 顾问表的主键id,存在这个顾问,才可以写入,允许为空
native_place = Column(VARCHAR(100)
,nullable = True)
graduation_school = Column(VARCHAR(100)
,nullable = True)
major = Column(VARCHAR(100)
,nullable = True)
enrollment_date = Column(Date
,nullable = False)#入学时间必填
graduation_date = Column(Date,
nullable = True)#毕业时间可以为空
education = Column(VARCHAR(50)
,nullable = True)#学历可以为空
age = Column(Integer
,nullable = False)
gender = Column(VARCHAR(10)
,nullable = False)
create_at = Column(DATETIME
,default = datetime.now)
update_at = Column(DATETIME
,default = datetime.now
,onupdate = datetime.now)
is_deleted = Column(Integer
,default = 0)#逻辑删除,默认为0,为1则表示已删除
+63
View File
@@ -0,0 +1,63 @@
from sqlalchemy import (Column, Integer,VARCHAR,DateTime
)
from sqlalchemy.dialects.mssql import TINYINT
from core.database import Base
from datetime import datetime
# teachers 老师表 ORM 模型
#字段包括id,teacher_no,teacher_name,phone,email,remark,created_at,updated_at,is_deleted
class Teacher(Base):
__tablename__ = 'teachers_info_detail'
id = Column(
Integer
, primary_key=True
,autoincrement=True
,comment='老师主键')
teacher_no = Column(
VARCHAR(50)
,nullable=False
,unique=True
,comment='老师编号'
)
teacher_name = Column(
VARCHAR(50)
,nullable=False
,comment='老师名字'
)
phone = Column(
VARCHAR(20)
,nullable=True
,comment='老师电话'
)
email = Column(
VARCHAR(100)
,nullable=True
,comment='邮箱'
)
remark = Column(
VARCHAR(2550)
,nullable=True
,comment='备注'
)
created_at = Column(
DateTime
,nullable=False
,default=datetime.now
,comment='创建时间'
)
updated_at = Column(
DateTime
,nullable=False
,default=datetime.now
,comment='更新时间'
)
is_deleted = Column(
TINYINT
,nullable=False
,default=0
,comment='逻辑删除'
)
+24
View File
@@ -0,0 +1,24 @@
from pydantic import BaseModel # 导入pydantic模块下的BaseModel类
from datetime import datetime,date # 导入datetime模块下的datetime,date类
# ————定义"创建班级"的"请求体"模型————
class ClassCreate( BaseModel ):
class_no: str
class_name: str
# ————定义"更新班级"的"请求体"模型————
class ClassUpdate( BaseModel ):
class_no: str|None = None
class_name: str|None = None
start_date : date|None = None
end_date : date|None = None
created_at : datetime|None = None
update_at : datetime|None = None
# ————定义"班级"的"响应体"模型————
class ClassResponse( BaseModel ):
code:int = 200
detail:str = '执行成功'
total:int = 0
data:str|dict|list|tuple
-33
View File
@@ -1,33 +0,0 @@
from pydantic import BaseModel
from datetime import datetime
from typing import Optional
# 新增顾问 请求体
class ConsultantCreate(BaseModel):
consultant_no: str
consultant_name: str
phone: Optional[str] = None
email: Optional[str] = None
remark: Optional[str] = None
# 修改顾问 请求体
class ConsultantUpdate(BaseModel):
consultant_name: Optional[str] = None
phone: Optional[str] = None
email: Optional[str] = None
remark: Optional[str] = None
# 返回模型
class ConsultantResponse(BaseModel):
id: int
consultant_no: str
consultant_name: str
phone: Optional[str]
email: Optional[str]
remark: Optional[str]
created_at: datetime
updated_at: datetime
+4
View File
@@ -0,0 +1,4 @@
class NoExist(Exception):
def __init__(self,value):
self.value = value
pass
+18
View File
@@ -0,0 +1,18 @@
from pydantic import BaseModel
from datetime import date
class StudentCreate(BaseModel):
student_no: str|None = None
student_name: str
class_id: int
consultant_id: int | None = None
native_place: str | None = None
graduate_school: str | None = None
major: str | None = None
enrollment_date: date
graduation_date: date | None = None
education: str | None = None
age: int
gender: str
+19
View File
@@ -0,0 +1,19 @@
from pydantic import BaseModel
from typing import Optional
from datetime import datetime
#===============老师表===================
#===============请求体模型================
class TeacherCreate(BaseModel):
teacher_no: Optional[str] = None
teacher_name: Optional[str] = None
email: Optional[str] = None
phone: Optional[str] = None
remark: Optional[str] = None
class TeacherUpdate(BaseModel):
teacher_no: Optional[str] = None
teacher_name: Optional[str] = None
email: Optional[str] = None
phone: Optional[str] = None
remark: Optional[str] = None