Flask框架——模型关系(多对多)
上篇文章学习了Flask框架——模型关系(一对多关系),这篇文章我们学习Flask框架——模型关系(多对多关系)。
我们拿学生和课程为例子,一个学生可以选多门课程,一门课程可以被多名学生选,所以它们是多对多关系,我们假设数据库中学生表与课程表如下图所示:
如何使这两张表建立联系呢,是在课程表中多加一个字段来表示哪个学生选了这门课吗?
假如是在课程表中多加一个字段,每门课只能被一个学生选,那么该怎么办好呢?
想要两张表建立联系,多加一个字段不行的话,那么我们多建一张表不就好了吗?如下图所示:
通过创建第三张表来使学生表与课程表建立关系,第三张表我们称为关系表,数据库是这样设计,那么如何使模型之间产生联系呢,如何编写模型之间产生联系的代码呢?
在编写模型类代码之前,首先我们创建一个Flask项目,其目录如下所示:
创建好项目后,我们开始编写配置文件settings.py的代码,如下所示:
class Configs:
ENV='development'
DEBUG=True
# 设置连接数据库路径
SQLALCHEMY_DATABASE_URI='mysql+pymysql://root:123456@127.0.0.1:3306/test'
# 每次请求结束后自动提交数据库中的改动
SQLALCHEMY_COMMIT_ON_TEARDOWN=True
# 禁用SQLAlchemy对追踪对象的修改并且发送信号
SQLALCHEMY_TRACK_MODIFICATIONS = False
编写好配置文件后,我们将配置文件导入app.py文件中,代码如所示:
from flask import Flask
from settings import Config
app = Flask(__name__)
app.config.from_object(Config) # 加载配置
编写模型类
好了,Flask框架的基础配置已经写好了,接下来我们在app.py文件中编写学生模型类与课程模型类,代码如下所示:
from flask_sqlalchemy import SQLAlchemy
# 创建映射对象db
db=SQLAlchemy(app=app,use_native_unicode="utf8")
#Student模型类
class Student(db.Model):
__tablename__ = 'student' # 数据表名
id=db.Column(db.Integer,primary_key=True) #学生id
name=db.Column(db.String(20),nullable=False) #学生名
password=db.Column(db.Integer,nullable=False) #密码
#Course模型类
class Course(db.Model):
__tablename__='course' #数据表名
id=db.Column(db.Integer,primary_key=True) #课程id
course_name=db.Column(db.String(50),nullable=False) #课程名
credit=db.Column(db.Float,nullable=False) #学分
students = db.relationship('Student', backref='course', secondary='student_course') #设置studens字段,使Course模型类与Student模型类产生联系
这里我们在Course模型类中添加了students字段,该字段使用了db.relationship()方法让Course模型与Student模型产生了联系,当然也可以在Student模型类中添加course字段并使用db.relationship()方法使Student模型与Course模型产生联系,在Student模型类添加字段代码如下所示:
course = db.relationship('Course', backref='student', secondary='student_course')
其中:
- 'Course'参数是你要产生联系的模型类;
- backref是反向引用,其值可以是任意字符,该字符很重要,可以调用关联模型类的属性字段;
- secondary的值是关系数据表的表名。
注意:db.relationship()方法只能在两个相关联的模型类中任意选择一个调用,也就是说只能在Course模型类或者Student模型类中调用。
好了,学生模型类和课程模型类已经写好了,不知道你们有没有发现,学生模型与课程模型都没有设置外键的代码,这是因为外键要设置在关系数据表中,接下来编写关系数据表的模型类代码,代码如下所示:
#第三张数据表模型类
class Student_Course(db.Model):
__tablename__='student_course' #数据表名
id=db.Column(db.Integer,primary_key=True) #id
student_id=db.Column(db.Integer,db.ForeignKey('student.id')) #学生id
course_id=db.Column(db.Integer,db.ForeignKey('course.id')) #课程id
当还有其他模型类要关联时,只要在上面的模型类添加外键字段即可。
除了这样设置关系数据表外,我们还可以通过db.Table()方法来设置,代码如下所示:
tags=db.Table('student_course', #数据表名
db.Column('id',db.Integer,primary_key=True) #id
db.Column('student_id',db.Integer,db.ForeignKey('student.id')), #学生id
db.Column('course_id',db.Integer,db.ForeignKey('course.id')) #课程id
)
其中:student_id为数据表的字段,db.Integer为字段的数据类型,这里是整型,db.ForeignKey()方法传递的是模型类.模型类主键。
好了,模型类代码已经写好了,接下来我们通过在app.py中编写代码创建数据表,其代码如下所示:
if __name__ == '__main__':
db.create_all() #创建数据表
app.run()
在终端执行app.py后,就成功创建好数据表了,下面我们在pycharm中看看这三张表的联系,如下图所示:
这样就成功把student数据表与course数据表联系起来了,我们手动为这三张表添加数据,如下图所示:
接下来我们将通过学生来找出该学生选的课程和通过课程来找出该课程被哪些学生。
通过学生找课程
首先编写视图函数,代码如下所示:
@app.route('/findcourse')
def course():
student_id=request.args.get('id') #获取学生id
student=Student.query.get(student_id) #获取学生数据
return render_template('course.html',student=student) #通过render_template()方法将course.html完整地呈现在网页中,并传递student学生数据到网页中
编写好视图函数后,接下来在templates文件夹中创建一个名为course的html文件,其代码如下所示:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>学生找已选课程</title>
</head>
<body>
学生名:{{ student.name }}
<br>
该学生选了以下课程:
{% for course in student.course %}
<p>{{ course.course_name }}---{{ course.credit }}学分</p>
{% endfor %}
</body>
</html>
第八行代码,我们将传递过来的student中获取学生名,在第十一行代码中,我们利用Course模型类中的反向引用backref参数值course,通过student.course就可以获取课程对象,通过课程对象来获取课程名、课程学分。在终端执行app.py,并在浏览器中打开http://127.0.0.1:5000/findcourse?id=2022001,如下图所示:
这里我们找了学号为2022001,其选了Python程序设计、数据分析、数据可视化。
通过课程找学生
首先编写视图函数,代码如下所示:
@app.route('/findstudent')
def student():
course_id=request.args.get('id') #获取课程id
courses=Course.query.get(course_id) #获取课程数据
return render_template('student.html',courses=courses) #通过render_template()方法将student.html完整地呈现在网页中,并传递courses学生数据到网页中
编写好视图函数后,接下来在templates文件夹中创建一个名为student的html文件,其代码如下所示:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>通过课程找学生</title>
</head>
<body>
课程名:{{ courses.course_name }}
<br>
选择该课程的学生有:
{% for student in courses.students %}
<p>{{ student.name }}---学号:{{ student.id }}</p>
{% endfor %}
</body>
</html>
第八行代码,通过传递的courses数据获取课程名,第十一行代码,使用了Course模型类中students字段,通过courses.students获取到了学生对象,再通过学生对象获取学生名、学号。
在终端执行app.py,并在浏览器中打开http://127.0.0.1:5000/findstudent?id=003,如下图所示:
这里我们获取课程id为003,其学生有张三,学号为2022001。
通过关系数据表使另外两张数据表产生了联系,并可以互相获取到数据。
好了,Flask框架——模型关系(多对多关系)就讲到这里了,下篇文章继续学习Flask框架——Session与Cookie,感谢观看!!!
公众号:白巧克力LIN