初始化前后端学生管理系统项目

This commit is contained in:
2026-09-21 19:15:28 +08:00
commit 8a35871cea
63 changed files with 5723 additions and 0 deletions
+15
View File
@@ -0,0 +1,15 @@
# 请求体
from pydantic import BaseModel, Field
class ScoreCreate(BaseModel):
stu_id: int=Field(...,ge=1,description='学生id必须大于等于1')
exam_id: int=Field(...,ge=1,description='考核序次必须大于等于1')
score: int=Field(...,ge=0,le=100,description='成绩必须在0-100之间')
class ScoreUpdate(BaseModel):
# stu_id: int = Field(None, ge=1, description='学生id必须大于等于1')
# exam_id: int = Field(None, ge=1, description='考核序次必须大于等于1')
score: int = Field(None, ge=0, le=100, description='成绩必须在0-100之间')
+12
View File
@@ -0,0 +1,12 @@
from datetime import datetime
from pydantic import BaseModel,Field
#引入Pydantic数据校验。
class AdvisorIn(BaseModel):
advisor_id: int=Field(...,ge=1,description="顾问ID")
advisor_name: str=Field(...,min_length=2,max_length=8,description="姓名为2~8个字符")
class AdvisorOut(BaseModel):
advisor_id: int
advisor_name: str
class Config:
from_attributes = True
+34
View File
@@ -0,0 +1,34 @@
from pydantic import BaseModel, Field, ConfigDict # BaseModel=模型基类,Field=字段规则,ConfigDict=模型配置
from datetime import date # Python的日期类型(只有年月日)
from typing import Optional # Optional[X] 表示"可以是X,也可以是None"
# ---------------- 请求模型 ----------------
# 新增班级:class_id、start_time 必填
# 请求模型 = 前端传过来的数据长什么样,FastAPI自动帮你校验
class ClassCreate(BaseModel):# 新增班级的入参模型:POST新增时,请求体必须符合这个结构
class_id: int = Field(..., ge=1, description="班级编号,正整数,不能重复")
start_time: date = Field(..., description="开班日期,格式 yyyy-MM-dd")
# description:这行字会显示在Swagger文档里,方便前端看
# 修改班级:字段可选,前端传哪个改哪个(局部更新)
class ClassUpdate(BaseModel):
# class_id: int = Field( ge=1, description="班级编号,可选") 被注释掉 = 不允许修改班级编号
start_time: Optional[date] = Field(None, description="开班日期,格式 yyyy-MM-dd")
# Optional[date] = 可以传日期也可以不传;Field(None) = 不传时默认值是None
# ---------------- 响应模型 ----------------
# 响应模型:后端返回给前端的数据结构,from_attributes 允许直接从 ORM (Classinfo实例)的属性取值,不用手动一个个赋值
class ClassResponse(BaseModel):
model_config = ConfigDict(from_attributes=True)
class_id: int # 返回字段:班级编号
start_time: date# 返回字段:开班日期
#逻辑:**三个模型管三种场景**—— 新增(必填)、修改(可选)、响应(输出)。
# 前端传错类型 / 缺字段,FastAPI 直接返回 422,不会把脏数据送进数据库。
+65
View File
@@ -0,0 +1,65 @@
# 就业开放时间和offer下发时间校验
# 导入基类、过滤条件、校验器
from pydantic import BaseModel, Field, model_validator, field_validator
# 导入时间模块
from datetime import date, datetime
# 导入可选类型、列表类型
from typing import Optional, List
# ---------- 请求模型 ----------
# 修改就业记录
class EmploymentOfferUpdate(BaseModel):
offer_time: Optional[date] = None
# 修改就业基础
class EmploymentBaseUpdate(BaseModel):
employment_open_time: Optional[date] = None
job_time: Optional[date] = None
company_name: Optional[str] = None
salary: Optional[float] = None
# 添加就业基础
class EmploymentBaseCreate(BaseModel):
stu_id: int = Field(..., description="学生编号")
job_time: Optional[date] = Field(None, description="实际去就职时间")
employment_open_time: date = Field(description="就业开放时间:年-月-日")
company_name: str = Field(max_length=100, description="就业公司")
salary: float = Field(..., gt=0, description="就业薪资,保留2位小数")
# 添加就业记录
class EmploymentOfferCreate(BaseModel):
stu_id: int = Field(..., description="学生编号")
offer_id: int = Field(..., description="offer编号")
offer_time: date = Field(description="offer下发时间:年-月-日")
# 多条件组合查询
class EmploymentQuery(BaseModel):
stu_id: Optional[int] = None
company_name: Optional[str] = Field(None, max_length=100, description="公司名称")
min_salary: Optional[float] = None
max_salary: Optional[float] = None
# ---------- 响应模型 ----------
# 就业记录查询响应
class EmploymentOfferQueryResponse(BaseModel):
stu_id: int
offer_id: int
offer_time: date
class Config:
from_attributes = True
# 就业基础查询响应
class EmploymentBaseQueryResponse(BaseModel):
stu_id: int
employment_open_time: Optional[date] = None
job_time: Optional[date] = None
company_name: Optional[str] = None
salary: Optional[float] = None
class Config:
from_attributes = True
+36
View File
@@ -0,0 +1,36 @@
from pydantic import BaseModel, Field, model_validator
class StudentAge(BaseModel):
age_star: int | None = Field(None, gt=0)
age_end: int | None = Field(None, gt=0)
age_value: int | None = Field(None, gt=0)
@model_validator(mode="after")
def check_age(self):
if self.age_value is not None:
if self.age_star is not None or self.age_end is not None:
raise ValueError('age_value和age_star/age_end区间不能同时存在')
else:
if self.age_star is None or self.age_end is None:
raise ValueError('区间需填写完整')
if self.age_star is not None and self.age_end is not None:
if self.age_star > self.age_end:
raise ValueError('输入起始值不能大于终止值')
return self
class ClassCount(BaseModel):
class_id: int = Field(..., gt=0)
gender: str | None = Field(None, description="可填男/女")
class ScoreCount(BaseModel):
score: int = Field(..., ge=0, le=100)
num: int | None = Field(None, gt=0)
class ScoreAvg(BaseModel):
exam_order: int = Field(...)
class Employment(BaseModel):
top: int = Field(...)
class EmploymentOff(BaseModel):
class_id: int = Field(...)
+67
View File
@@ -0,0 +1,67 @@
# scheme/student.py
from pydantic import BaseModel, Field,model_validator
from datetime import datetime, date
from typing import Optional
# ---------- 请求体模型 ----------
class StudentCreate(BaseModel):
stu_id: int = Field(..., ge = 1)
class_id: int = Field(..., ge = 1)
advisor_id: int = Field(..., ge=1, description="顾问老师id,对应 advisors.advisor_id")
stu_name: str = Field(..., min_length=1, max_length=10)
native_place: str = Field(..., min_length=1, max_length=30)
graduate_school: str = Field(..., min_length=1, max_length=50)
education: str = Field(..., min_length=1, max_length=10)
major: str = Field(..., min_length=1, max_length=20)
age: int = Field(..., ge = 18, le =40)
gender: str = Field(..., min_length=1, max_length=20)
graduate_time:date= Field(...)
enroll_time:date= Field(...)
# 模型校验,时间判断
# @model_validator (mode = "after")
# def check_time(self):
# # 入学时间不能晚于就业时间
# if self.graduate_time is not None:
# if self.graduate_time < self.enroll_time:
# raise ValueError ("毕业时间不能早于入学时间!!!")
# # 简历开放时间不能早于入学时间
# # if self.employment_open_time < self.enroll_time:
# # raise ValueError("简历开放时间不能早于入学时间")
# # 简历开放时间不能晚于毕业时间
# if self.graduate_time is not None:
# if self.graduate_time < self.employment_open_time:
# raise ValueError("简历开放时间不能晚于毕业时间!!!")
# # mode="after" 的校验器必须返回 self,否则 Pydantic v2 会把整个模型变成 None
# return self
class StudentUpdate(BaseModel):
class_id: Optional[int] = Field(None)
advisor_id: Optional[int] = Field(None, ge=1)
stu_name: Optional[str] = Field(None, min_length=1, max_length=10)
native_place: Optional[str] = Field(None, min_length=1, max_length=30)
graduate_school: Optional[str] = Field(None, min_length=1, max_length=50)
education: Optional[str] = Field(None, min_length=1, max_length=10)
major: Optional[str] = Field(None, min_length=1, max_length=20)
age: Optional[int] = Field(None, ge = 18, le =40)
gender: Optional[str] = Field(None, min_length=1, max_length=20)
# ----------响应体模型-------------
class StudentResponse(BaseModel):
stu_id: int
class_id: int # 数据库非空,这里必须是 int
stu_name: str
native_place: str
graduate_school: Optional[str]
education: str
major: Optional[str]
# 敏感字段已在此模型中脱敏
class Config:
from_attributes = True #支持orm对象转换,让pydantic可以读取ORM数据库对象(SQLAlchemy模型)
+52
View File
@@ -0,0 +1,52 @@
# 正确
from pydantic import Field
from datetime import datetime
from typing import Optional
from pydantic import BaseModel, field_validator
# --------------------请求体模型-----------------------------
# 用于增加1行数据# 加了软删除标签
class TeacherAdd(BaseModel):
teacher_id:int=Field(...,ge=1,description='教师ID是整数类型')
class_id:int=Field(...,ge=1,description='班级ID是整数类型')
teacher_name:str=Field(...,description='教师姓名')
job_name:str=Field(...,min_length=2,description='主讲老师、班主任、助教')
is_deleted:int=Field(0,ge=0,le=0,description='只能输入0,0代表未删除,1代表已经被软删除')
@field_validator("job_name")
@classmethod
def validate_job_name(cls, v):
"""校验 job_name 必须是 主讲/班主任/助教 之一"""
allowed = ["主讲老师", "班主任", "助教"]
if v not in allowed:
raise ValueError(f"job_name 必须是 {allowed} 之一,当前值: {v}")
return v
# 用于更新数据
class TeacherUpdate(BaseModel):
class_id: Optional[int] = Field(None, ge=1, description='班级ID是整数类型') # ge=1 只对非 None 的值生效
teacher_name: Optional[str] = Field(None, description='教师姓名')
job_name: Optional[str] = Field(None,min_length=2, description='主讲老师、班主任、助教')
@field_validator("job_name")
@classmethod
def validate_job_name(cls, v):
"""校验 job_name 必须是 主讲/班主任/助教 之一"""
allowed = ["主讲老师", "班主任", "助教"]
if v not in allowed:
raise ValueError(f"job_name 必须是 {allowed} 之一,当前值: {v}")
return v
# --------------------- 响应模型 ----------------------------
class TeacherResponse(BaseModel):
teacher_id: int
class_id: int
teacher_name: str
job_name: str
class Config: # 告诉 Pydantic:"可以从任意对象的属性中读取数据,而不只是从字典中读取。"
from_attributes = True # 支持 ORM 对象转换