Python之Flask框架~多表操作~一对多
1.定义
“一对多”是指关系型数据库中的模型对象的一对多的模型关系,它表示一个模型(即表)的一条记录(即行)对应多个另一个模型(即另一个表)的记录。简单来说,一个模型中的一个记录关联另一个模型中的多个记录。比如一个班级对象有多个学生对象。
以班级对象以及学生对象为例写个代码
# 班级模型
class Grade(db.Model):
__tablename__ = 'grade' # 班级表名
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
grade_name = db.Column(db.String(30), unique=True) # 班级名称
"""
建立关联
第一个参数:关联的模型名(表)
第二个参数:反向引用的名称,grade对象,让student反过来得到grade对象的名称:student.grade
第三个参数:懒加载
"""
students = db.relationship('Student', backref='grade', lazy=True)
# 学生模型
class Student(db.Model):
__tablename__ = 'student' # 学生表名
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
student_name = db.Column(db.String(30), unique=True) # 学生名字
age = db.Column(db.Integer, default=1) # 学生年龄,默认1岁
# 外键:跟Grade对象的id关联
gradeid = db.Column(db.Integer, db.ForeignKey(Grade.id))
关键点:
(1)外键是在一对多中的多的一方,原因是为了方便数据的处理,加入把外键放在“一”这一方,就会出现班级模型对象中的外键某行的值会有多个学生id,在进行数据操作时候还得查找出来具体的学生id去关联学生对象模型的学生数据,这样就显得比较麻烦;
(2)在主键对象模型上建立关联属性,在此例子中就是“students = db.relationship('Student', backref='grade', lazy=True)” ,这样做的好处就是可以通过班级对象查找出对于的学生数据,也可以通过学生对象反向查找出班级数据.
2.数据操作
在进行数据迁移操作之后就可以看到相应的数据表了
(1)增
a.增加班级数据
@user_bp.route("/addgrad")
def add_grade():
# 班级列表
grade_list = []
for i in range(10):
# 班级名
grd = Grade()
grd.grade_name = f'终极{i}班'
grade_list.append(grd)
try:
# 添加班级列表
db.session.add_all(grade_list)
db.session.commit()
return "添加班级成功!"
except:
db.session.rollback() # 回滚
b.添加学生
@user_bp.route("/addstu")
def add_student():
# 学生列表
student_list = []
for i in range(20):
# 学生名
std = Student()
std.student_name = f'jason{i}-{random.randint(15,99)}'
std.age = random.randint(15,18)
std.gradeid = random.randint(5,8)
student_list.append(std)
try:
# 添加学生列表
db.session.add_all(student_list)
db.session.commit()
return "添加学生成功!"
except:
db.session.rollback() # 回滚
(2)删
删除班级信息
@user_bp.route("/delgrd/<int:grd_id>")
def del_grd(grd_id):
grd_obj = Grade.query.get(grd_id)
try:
# 删除班级
db.session.delete(grd_obj)
db.session.commit()
return "删除班级信息成功!"
except:
db.session.rollback() # 回滚
return "删除班级信息失败!"
删除学生信息
@user_bp.route("/delstu/<int:stu_id>")
def del_std(stu_id):
stu_obj = Grade.query.get(stu_id)
try:
# 删除学生
db.session.delete(stu_obj)
db.session.commit()
return "删除学生信息成功!"
except:
db.session.rollback() # 回滚
return "删除学生信息失败!"
如图所示,删除了id为6的学生
(3)改
①更改班级信息
@user_bp.route("/updgra")
def update_grad():
# 将前两个id的班级名称的前两个字变为“终极”
try:
for i in range(1, 3):
g = Grade.query.get(i)
g_name = g.grade_name
g.grade_name = g_name.replace(g_name[:2], '终极')
db.session.commit()
return "更新班级信息成功!"
except:
db.session.rollback() # 回滚
print(traceback.format_exc())
return "更新班级信息失败!"
②更改学生信息
@user_bp.route("/updstu")
def update_stu():
# 将年龄小于18岁的学生的年龄改为18岁
stu_obj = Student.query.filter(Student.age.__lt__(18))
try:
for s in stu_obj:
s.age = 18
db.session.commit()
return "更新学生信息成功!"
except:
db.session.rollback() # 回滚
print(traceback.format_exc())
return "更新学生信息失败!"
(4)查
查询班级信息
@user_bp.route("/getgra")
def get_gra():
# 查询终极5班有多少个学生
count_stu = Student.query.filter(Student.gradeid == Grade.query.filter(Grade.grade_name == "终极5班").first().id).count()
try:
return f"终极5班有{count_stu}个学生"
except:
db.session.rollback() # 回滚
print(traceback.format_exc())
return "查询终极5班的学生人数失败!"
查询学生信息
@user_bp.route("/getstu")
def get_stu():
# 查询id为18的学生属于哪个班级
gra_info = Student.query.get(18).grade.grade_name
try:
return f"id为18的学生属于{gra_info}!"
except:
db.session.rollback() # 回滚
print(traceback.format_exc())
return f"查询id为18的学生的班级失败!"
The end !Thanks