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

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,837評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,196評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,688評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,654評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,456評論 6 406
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,955評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,044評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,195評論 0 287
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,725評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,608評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,802評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,318評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,048評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,422評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,673評論 1 281
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,424評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,762評論 2 372

推薦閱讀更多精彩內容