




版權說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權,請進行舉報或認領
文檔簡介
第Flasksqlalchemy一對多與多對一與一對一及多對多關系介紹目錄配置項定義外鍵定義關系屬性雙向的關系屬性使用關系屬性添加數(shù)據(jù)一對一多對多這里以作者和文章來演示一對多的關系:一個作者可以有多篇文章,但是一篇文章只能有一個作者。
配置項
首先,配置下數(shù)據(jù)庫config.py
username='xxxx'
password='xxxx'
database='school'
hostname='localhost'
port='3306'
uri=f'mysql+pymysql://{username}:{password}@{hostname}:{port}/{database}'
SQLALCHEMY_DATABASE_URI=uri
SQLALCHEMY_TRACK_MODIFICATIONS=False
在app.py文件中導入配置
fromflaskimportFlask
fromflask_sqlalchemyimportSQLAlchemy
importconfig
app=Flask(__name__)
app.config.from_object(config)
db=SQLAlchemy(app)
接著創(chuàng)建模型類,建立python類到數(shù)據(jù)表的映射:
定義外鍵
classUser(db.Model):
__tablename__='user'
id=db.Column(db.Integer,primary_key=True,autoincrement=True)
name=db.Column(db.String(100),nullable=False)
classArticle(db.Model):
__tablename__='article'
id=db.Column(db.Integer,primary_key=True,autoincrement=True)
title=db.Column(db.String(200),nullable=False)
content=db.Column(db.Text,nullable=False)
user_id=db.Column(db.Integer,db.ForeignKey('user.id'))
由于一個作者可以有多篇文章,所以外鍵應該設置在Article類中,這樣每一篇文章的user_id字段都只會有一個值,因為只對應一個作者。
假設,在User類中存在外鍵字段article_id,那么一個作者的所有文章都需要存放在這一個字段中,但是外鍵只能存放單一數(shù)據(jù)(表量),所以外鍵的設置總是在多的這一側(cè)定義。
定義關系屬性
為什么需要關系屬性,具體的原因我也不清楚,我想可能是從查詢的角度來說,會更方便。
定義關系屬性需要使用關系函數(shù)。關系屬性在關系的出發(fā)側(cè)定義,即一對多關系的一這一側(cè)。一個作者擁有多篇文章,我們在User模型類中,定義一個叫articles的關系屬性,用它可以表示每一個作者所對應的多篇文章。
classUser(db.Model):
__tablename__='user'
id=db.Column(db.Integer,primary_key=True,autoincrement=True)
name=db.Column(db.String(100),nullable=False)
articles=db.relationship('Article',backref=db.backref('user'))
articles字段使用db.relationship()關系函數(shù)定義為關系屬性,這個關系屬性將返回多個記錄。
relationship()函數(shù)的第一個參數(shù)為關系另一側(cè)的模型名稱,是python類的名稱,不是數(shù)據(jù)表名稱。第二個參數(shù)表示添加反向引用,會自動在另一側(cè),也就是Article模型中,建立一個關系屬性,這個字段叫user,使用這個字段可以查找到文章所對應的用戶。
現(xiàn)在user表中多了一個字段articles,但是它并不是數(shù)據(jù)庫層面的,實際的表中并沒有這個字段,可以認為只是一個查詢接口。
接著創(chuàng)建數(shù)據(jù)表并插入數(shù)據(jù):
u1=User(name='zs')
a1=Article(title='西游記',content='西游記是四大名著')
a1.author=u1
db.session.add(a1)
mit()
創(chuàng)建了一個user表的記錄,一個article表的記錄,如何讓他們建立聯(lián)系呢?使用關系屬性字段:
文章唯一指向一個作者:
a1.author=u1
直接將作者的實例對象u1賦值給文章實例對象a1的author字段,他們就會建立關系,文章表中的user_id字段就會指向那個作者。
article表
user表
現(xiàn)在用戶zs擁有兩篇文章,嘗試使用關系屬性查詢。
u1=User.query.filter_by(name='zs').first()
print(u1.articles)
輸出user表的articles字段:
[Article1,Article2]
可以發(fā)現(xiàn)這個字段里面是兩條記錄,是article表中的兩條記錄,因為這兩篇文章都是zs的文章,所以通過這個關系屬性字段,可以獲取到一個作者對應的所有文章。
反過來,關于反向引用,backref=db.backref(user),它會在Article也建立一個關系屬性,這個字段叫做user,可以通過這個字段獲取到文章對應的作者。
比如:
#先找到文章
article1=Article.query.filter_by(title='西游記').first()
#使用反向引用的字段,user,獲取到這個文章對應的作者
print(article1.user)
輸出:
User1
雙向的關系屬性
上面在建立關系屬性是,只是在User類中使用了關系屬性:
articles=db.relationship('Article',backref=db.backref('user'))
這種方式,會隱式的在Article類中也建立一個關系屬性user。我們可以使用back_populates參數(shù)顯式的建立雙向的關系屬性。
這里仍然以作者author和文章article為例,一個作者可以有多篇文章,一篇文章只能有一個作者,建立顯示的雙向關系屬性。
classUser(db.Model):
__tablename__='author'
id=db.Column(db.Integer,primary_key=True,autoincrement=True)
name=db.Column(db.String(100),nullable=False)
#關系屬性
articles=db.relationship('Article',back_populates='authors')
classArticle(db.Model):
__tablename__='article'
id=db.Column(db.Integer,primary_key=True,autoincrement=True)
title=db.Column(db.String(200),nullable=False)
content=db.Column(db.Text,nullable=False)
auth_id=db.Column(db.Integer,db.ForeignKey('author.id'))
#關系屬性
authors=db.relationship('User',back_populates='articles')
在一的一側(cè),User類中,建立了關系屬性,articles,獲取一個作者對應的多個文章記錄。
在多的一側(cè),Article類中,建立了關系屬性,authors,獲取每一篇文章對應的一個作者記錄。
使用back_populates參數(shù)連接對方,參數(shù)值需要設置為關系另一側(cè)的關系屬性名。
使用關系屬性添加數(shù)據(jù)
u1=User(name='zs')
a1=Article(title='西游記',content='西游記是四大名著')
a2=Article(title='紅樓夢',content='紅樓夢是四大名著')
a1.authors=u1
a2.authors=u1
db.session.add_all([a1,a2])
mit()
實例化User類對象u1,Article類對象a1,a2。
然后使用Article類的關系屬性字段,authors
將User類對象u1賦值給Article類對象的關系屬性authors
或者反過來,使用用戶的關系屬性字段articles添加數(shù)據(jù):
definsert():
u1=User(name='zs')
a1=Article(title='西游記',content='西游記是四大名著')
a2=Article(title='水滸傳',content='水滸傳是四大名著')
u1.articles=[a1,a2]
db.session.add(u1)
mit()
這里的添加方式是:u1.articles=[a1,a2]
接著查詢,使用關系屬性字段就可以查詢到了,這里只是演示了使用back_populates參數(shù)顯示的建立雙向的關系屬性,之前使用的backref可以簡化關系的定義,是一種隱式的雙向關系的建立。
一對一
這里使用國家和首都演示一對一關系:每一個國家只有一個首都;反過來說,一個城市也只能作為一個國家的首都。
一對一關系實際上是通過建立雙向關系的一對多關系的基礎上轉(zhuǎn)化而來的。
classCountry(db.Model):
__tablename__='country'
id=db.Column(db.Integer,primary_key=True,autoincrement=True)
name=db.Column(db.String(30),unique=True)
capital=db.relationship('Capital',back_populates='country')
classCapital(db.Model):
__tablename__='capital'
id=db.Column(db.Integer,primary_key=True,autoincrement=True)
name=db.Column(db.String(30),unique=True)
#外鍵在哪一個表中設置應該都可以
country_id=db.Column(db.Integer,db.ForeignKey('country.id'))
#設置關系屬性
country=db.relationship('Country',back_populates='capital')
首先上面是一個雙向的關系屬性,這時候表的關系和之前的一對多沒有區(qū)別,現(xiàn)在我們需要給關系屬性中假如一個參數(shù)uselist=False
在一的一側(cè)加入,就是在Country類模型中加入
capital=db.relationship('Capital',back_populates='country',uselist=False)
加入這個參數(shù)以后,在使用Country.capital獲取記錄時,將限制只返回一條記錄。
由于Capital中設置了外鍵country_id,存儲單一數(shù)據(jù),一個記錄的country_id只會對應Country中的一個記錄。
這是一對多關系就變成了一對一關系。
測試一對一:
首先插入數(shù)據(jù),插入一個國家記錄,一個城市記錄,然后建立關系。
definsert():
china=Country(name='中國')
Beijing=Capital(name='北京')
Beijing.country=china
db.session.add(Beijing)
mit()
這樣,Country表中就有了
capital表中:
他們目前時一對一的關系,那么,假如現(xiàn)在新增一個城市,它的country_id指向中國,
這時候就變成了一個國家,對應兩個城市,變成了一對多,但是我們定義的是一對一,這樣可行嗎?
deff():
#首先拿到中國的這條記錄
china=Country.query.filter_by(name='中國')
china=china.first()
print(china)
#新增城市,
Guangzhou=Capital(name='廣州')
#建立廣州與中國之間的關系
Guangzhou.country=china
db.session.add(Guangzhou)
mit()
print('success')
執(zhí)行這個函數(shù)之后,數(shù)據(jù)表會有以下變化:
可以看到capital表中的北京這條記錄的country_id值變成了NULL,這正是因為我們建立的關系時一對一的,不允許變成一對多,所以,會把之前的對應關系取消掉。假如刪除了參數(shù)uselist=False,就可以建立一對多的關系了。
多對多
這里使用學生和老師來演示多對多關系:每個學生有多個老師,每個老師也可以有多個學生。
在一對多關系中,我們可以在多這一側(cè)添加外鍵指向一這一側(cè),外鍵只能存儲一個記錄,但是在多對多關系中,每一個記錄都可以與關系另一側(cè)的多個記錄建立關系,關系兩側(cè)的模型都需要存儲一組外鍵。
在SQLAlchemy中,要想表示多對多關系,除了關系兩側(cè)的模型外,我們還需要創(chuàng)建一個關聯(lián)表(associationtable)。關聯(lián)表不存儲數(shù)據(jù),只用來存儲關系兩側(cè)模型的外鍵對應關系,
fromflaskimportFlask
fromflask_sqlalchemyimportSQLAlchemy
importconfig
app=Flask(__name__)
app.config.from_object(config)
db=SQLAlchemy(app)
association_table=db.Table('stu_tea_associ',#關聯(lián)表的名稱
db.Column('student_id',db.Integer,db.ForeignKey('student.id')),#字段student_id,類型,關聯(lián)的外鍵
db.Column('teacher_id',db.Integer,db.ForeignKey('teacher.id')))#字段teacher_id,類型,關聯(lián)的外鍵
classStudent(db.Model):
__tablename__='student'
id=db.Column(db.Integer,primary_key=True,autoincrement=True)
name=db.Column(db.String(20))
#建立關系屬性
teachers=db.relationship('Teacher',secondary=association_table,back_populates='students')
classTeacher(db.Model):
__tablename__='teacher'
id=db.Column(db.Integer,primary_key=True,autoincrement=True)
name=db.Column(db.String(20))
#建立關系屬性
students=db.relationship('Student',secondary=association_table,back_populates='teachers')
關聯(lián)表使用db.Table類定義,傳入的第一個參數(shù)是關聯(lián)表的名稱。我們在關聯(lián)表中定義了兩個字段student_id,teacher_id,這兩個字段作為外鍵,與student.id,t
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經(jīng)權益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 大學幸福人生規(guī)劃與實踐路徑
- 外架拆除安全專項施工方案
- 2025年2月育嬰員初級??荚囶}(含參考答案解析)
- 2024年3月中式面點師(中級)模擬試題(含參考答案解析)
- 2月藥物分析練習題含答案(附解析)
- 家具零售店面的市場分析與競爭對策考核試卷
- 罐頭湯料與調(diào)味品制造考核試卷
- 天澄環(huán)保某知名企業(yè)戰(zhàn)略梳理與管理診斷報告
- 紡織品及針織品行業(yè)競爭格局分析考核試卷
- 《C++多線程編程》課件
- 混凝土施工檢驗批質(zhì)量驗收記錄表
- 國有企業(yè)職務犯罪懲治與預防課件
- 門診病歷書寫模板全
- 鋼結(jié)構桁架吊裝安裝專項施工方案
- 課題研究活動記錄及課題研究會議記錄表
- 風電場道路工程施工方案
- 腫瘤細胞生物學1-1
- 中藥飲片的基礎知識和中藥飲片的養(yǎng)護培訓課件
- 4.個體工商戶登記(備案)申請表
- 2021年專業(yè)技術人員繼續(xù)教育公需科目考試試題及答案
- 油煙機清洗服務流程
評論
0/150
提交評論