




版權(quán)說(shuō)明:本文檔由用戶(hù)提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
第Flasksqlalchemy一對(duì)多與多對(duì)一與一對(duì)一及多對(duì)多關(guān)系介紹目錄配置項(xiàng)定義外鍵定義關(guān)系屬性雙向的關(guān)系屬性使用關(guān)系屬性添加數(shù)據(jù)一對(duì)一多對(duì)多這里以作者和文章來(lái)演示一對(duì)多的關(guān)系:一個(gè)作者可以有多篇文章,但是一篇文章只能有一個(gè)作者。
配置項(xiàng)
首先,配置下數(shù)據(jù)庫(kù)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文件中導(dǎo)入配置
fromflaskimportFlask
fromflask_sqlalchemyimportSQLAlchemy
importconfig
app=Flask(__name__)
app.config.from_object(config)
db=SQLAlchemy(app)
接著創(chuàng)建模型類(lèi),建立python類(lèi)到數(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'))
由于一個(gè)作者可以有多篇文章,所以外鍵應(yīng)該設(shè)置在Article類(lèi)中,這樣每一篇文章的user_id字段都只會(huì)有一個(gè)值,因?yàn)橹粚?duì)應(yīng)一個(gè)作者。
假設(shè),在User類(lèi)中存在外鍵字段article_id,那么一個(gè)作者的所有文章都需要存放在這一個(gè)字段中,但是外鍵只能存放單一數(shù)據(jù)(表量),所以外鍵的設(shè)置總是在多的這一側(cè)定義。
定義關(guān)系屬性
為什么需要關(guān)系屬性,具體的原因我也不清楚,我想可能是從查詢(xún)的角度來(lái)說(shuō),會(huì)更方便。
定義關(guān)系屬性需要使用關(guān)系函數(shù)。關(guān)系屬性在關(guān)系的出發(fā)側(cè)定義,即一對(duì)多關(guān)系的一這一側(cè)。一個(gè)作者擁有多篇文章,我們?cè)赨ser模型類(lèi)中,定義一個(gè)叫articles的關(guān)系屬性,用它可以表示每一個(gè)作者所對(duì)應(yīng)的多篇文章。
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()關(guān)系函數(shù)定義為關(guān)系屬性,這個(gè)關(guān)系屬性將返回多個(gè)記錄。
relationship()函數(shù)的第一個(gè)參數(shù)為關(guān)系另一側(cè)的模型名稱(chēng),是python類(lèi)的名稱(chēng),不是數(shù)據(jù)表名稱(chēng)。第二個(gè)參數(shù)表示添加反向引用,會(huì)自動(dòng)在另一側(cè),也就是Article模型中,建立一個(gè)關(guān)系屬性,這個(gè)字段叫user,使用這個(gè)字段可以查找到文章所對(duì)應(yīng)的用戶(hù)。
現(xiàn)在user表中多了一個(gè)字段articles,但是它并不是數(shù)據(jù)庫(kù)層面的,實(shí)際的表中并沒(méi)有這個(gè)字段,可以認(rèn)為只是一個(gè)查詢(xún)接口。
接著創(chuàng)建數(shù)據(jù)表并插入數(shù)據(jù):
u1=User(name='zs')
a1=Article(title='西游記',content='西游記是四大名著')
a1.author=u1
db.session.add(a1)
mit()
創(chuàng)建了一個(gè)user表的記錄,一個(gè)article表的記錄,如何讓他們建立聯(lián)系呢?使用關(guān)系屬性字段:
文章唯一指向一個(gè)作者:
a1.author=u1
直接將作者的實(shí)例對(duì)象u1賦值給文章實(shí)例對(duì)象a1的author字段,他們就會(huì)建立關(guān)系,文章表中的user_id字段就會(huì)指向那個(gè)作者。
article表
user表
現(xiàn)在用戶(hù)zs擁有兩篇文章,嘗試使用關(guān)系屬性查詢(xún)。
u1=User.query.filter_by(name='zs').first()
print(u1.articles)
輸出user表的articles字段:
[Article1,Article2]
可以發(fā)現(xiàn)這個(gè)字段里面是兩條記錄,是article表中的兩條記錄,因?yàn)檫@兩篇文章都是zs的文章,所以通過(guò)這個(gè)關(guān)系屬性字段,可以獲取到一個(gè)作者對(duì)應(yīng)的所有文章。
反過(guò)來(lái),關(guān)于反向引用,backref=db.backref(user),它會(huì)在Article也建立一個(gè)關(guān)系屬性,這個(gè)字段叫做user,可以通過(guò)這個(gè)字段獲取到文章對(duì)應(yīng)的作者。
比如:
#先找到文章
article1=Article.query.filter_by(title='西游記').first()
#使用反向引用的字段,user,獲取到這個(gè)文章對(duì)應(yīng)的作者
print(article1.user)
輸出:
User1
雙向的關(guān)系屬性
上面在建立關(guān)系屬性是,只是在User類(lèi)中使用了關(guān)系屬性:
articles=db.relationship('Article',backref=db.backref('user'))
這種方式,會(huì)隱式的在Article類(lèi)中也建立一個(gè)關(guān)系屬性u(píng)ser。我們可以使用back_populates參數(shù)顯式的建立雙向的關(guān)系屬性。
這里仍然以作者author和文章article為例,一個(gè)作者可以有多篇文章,一篇文章只能有一個(gè)作者,建立顯示的雙向關(guān)系屬性。
classUser(db.Model):
__tablename__='author'
id=db.Column(db.Integer,primary_key=True,autoincrement=True)
name=db.Column(db.String(100),nullable=False)
#關(guān)系屬性
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'))
#關(guān)系屬性
authors=db.relationship('User',back_populates='articles')
在一的一側(cè),User類(lèi)中,建立了關(guān)系屬性,articles,獲取一個(gè)作者對(duì)應(yīng)的多個(gè)文章記錄。
在多的一側(cè),Article類(lèi)中,建立了關(guān)系屬性,authors,獲取每一篇文章對(duì)應(yīng)的一個(gè)作者記錄。
使用back_populates參數(shù)連接對(duì)方,參數(shù)值需要設(shè)置為關(guān)系另一側(cè)的關(guān)系屬性名。
使用關(guān)系屬性添加數(shù)據(jù)
u1=User(name='zs')
a1=Article(title='西游記',content='西游記是四大名著')
a2=Article(title='紅樓夢(mèng)',content='紅樓夢(mèng)是四大名著')
a1.authors=u1
a2.authors=u1
db.session.add_all([a1,a2])
mit()
實(shí)例化User類(lèi)對(duì)象u1,Article類(lèi)對(duì)象a1,a2。
然后使用Article類(lèi)的關(guān)系屬性字段,authors
將User類(lèi)對(duì)象u1賦值給Article類(lèi)對(duì)象的關(guān)系屬性authors
或者反過(guò)來(lái),使用用戶(hù)的關(guān)系屬性字段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]
接著查詢(xún),使用關(guān)系屬性字段就可以查詢(xún)到了,這里只是演示了使用back_populates參數(shù)顯示的建立雙向的關(guān)系屬性,之前使用的backref可以簡(jiǎn)化關(guān)系的定義,是一種隱式的雙向關(guān)系的建立。
一對(duì)一
這里使用國(guó)家和首都演示一對(duì)一關(guān)系:每一個(gè)國(guó)家只有一個(gè)首都;反過(guò)來(lái)說(shuō),一個(gè)城市也只能作為一個(gè)國(guó)家的首都。
一對(duì)一關(guān)系實(shí)際上是通過(guò)建立雙向關(guān)系的一對(duì)多關(guān)系的基礎(chǔ)上轉(zhuǎn)化而來(lái)的。
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)
#外鍵在哪一個(gè)表中設(shè)置應(yīng)該都可以
country_id=db.Column(db.Integer,db.ForeignKey('country.id'))
#設(shè)置關(guān)系屬性
country=db.relationship('Country',back_populates='capital')
首先上面是一個(gè)雙向的關(guān)系屬性,這時(shí)候表的關(guān)系和之前的一對(duì)多沒(méi)有區(qū)別,現(xiàn)在我們需要給關(guān)系屬性中假如一個(gè)參數(shù)uselist=False
在一的一側(cè)加入,就是在Country類(lèi)模型中加入
capital=db.relationship('Capital',back_populates='country',uselist=False)
加入這個(gè)參數(shù)以后,在使用Country.capital獲取記錄時(shí),將限制只返回一條記錄。
由于Capital中設(shè)置了外鍵country_id,存儲(chǔ)單一數(shù)據(jù),一個(gè)記錄的country_id只會(huì)對(duì)應(yīng)Country中的一個(gè)記錄。
這是一對(duì)多關(guān)系就變成了一對(duì)一關(guān)系。
測(cè)試一對(duì)一:
首先插入數(shù)據(jù),插入一個(gè)國(guó)家記錄,一個(gè)城市記錄,然后建立關(guān)系。
definsert():
china=Country(name='中國(guó)')
Beijing=Capital(name='北京')
Beijing.country=china
db.session.add(Beijing)
mit()
這樣,Country表中就有了
capital表中:
他們目前時(shí)一對(duì)一的關(guān)系,那么,假如現(xiàn)在新增一個(gè)城市,它的country_id指向中國(guó),
這時(shí)候就變成了一個(gè)國(guó)家,對(duì)應(yīng)兩個(gè)城市,變成了一對(duì)多,但是我們定義的是一對(duì)一,這樣可行嗎?
deff():
#首先拿到中國(guó)的這條記錄
china=Country.query.filter_by(name='中國(guó)')
china=china.first()
print(china)
#新增城市,
Guangzhou=Capital(name='廣州')
#建立廣州與中國(guó)之間的關(guān)系
Guangzhou.country=china
db.session.add(Guangzhou)
mit()
print('success')
執(zhí)行這個(gè)函數(shù)之后,數(shù)據(jù)表會(huì)有以下變化:
可以看到capital表中的北京這條記錄的country_id值變成了NULL,這正是因?yàn)槲覀兘⒌年P(guān)系時(shí)一對(duì)一的,不允許變成一對(duì)多,所以,會(huì)把之前的對(duì)應(yīng)關(guān)系取消掉。假如刪除了參數(shù)uselist=False,就可以建立一對(duì)多的關(guān)系了。
多對(duì)多
這里使用學(xué)生和老師來(lái)演示多對(duì)多關(guān)系:每個(gè)學(xué)生有多個(gè)老師,每個(gè)老師也可以有多個(gè)學(xué)生。
在一對(duì)多關(guān)系中,我們可以在多這一側(cè)添加外鍵指向一這一側(cè),外鍵只能存儲(chǔ)一個(gè)記錄,但是在多對(duì)多關(guān)系中,每一個(gè)記錄都可以與關(guān)系另一側(cè)的多個(gè)記錄建立關(guān)系,關(guān)系兩側(cè)的模型都需要存儲(chǔ)一組外鍵。
在SQLAlchemy中,要想表示多對(duì)多關(guān)系,除了關(guān)系兩側(cè)的模型外,我們還需要?jiǎng)?chuàng)建一個(gè)關(guān)聯(lián)表(associationtable)。關(guān)聯(lián)表不存儲(chǔ)數(shù)據(jù),只用來(lái)存儲(chǔ)關(guān)系兩側(cè)模型的外鍵對(duì)應(yīng)關(guān)系,
fromflaskimportFlask
fromflask_sqlalchemyimportSQLAlchemy
importconfig
app=Flask(__name__)
app.config.from_object(config)
db=SQLAlchemy(app)
association_table=db.Table('stu_tea_associ',#關(guān)聯(lián)表的名稱(chēng)
db.Column('student_id',db.Integer,db.ForeignKey('student.id')),#字段student_id,類(lèi)型,關(guān)聯(lián)的外鍵
db.Column('teacher_id',db.Integer,db.ForeignKey('teacher.id')))#字段teacher_id,類(lèi)型,關(guān)聯(lián)的外鍵
classStudent(db.Model):
__tablename__='student'
id=db.Column(db.Integer,primary_key=True,autoincrement=True)
name=db.Column(db.String(20))
#建立關(guān)系屬性
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))
#建立關(guān)系屬性
students=db.relationship('Student',secondary=association_table,back_populates='teachers')
關(guān)聯(lián)表使用db.Table類(lèi)定義,傳入的第一個(gè)參數(shù)是關(guān)聯(lián)表的名稱(chēng)。我們?cè)陉P(guān)聯(lián)表中定義了兩個(gè)字段student_id,teacher_id,這兩個(gè)字段作為外鍵,與student.id,t
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶(hù)所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶(hù)上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶(hù)上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶(hù)因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 內(nèi)蒙古北方職業(yè)技術(shù)學(xué)院《跨境電商》2023-2024學(xué)年第二學(xué)期期末試卷
- 鞍山職業(yè)技術(shù)學(xué)院《企業(yè)領(lǐng)導(dǎo)學(xué)》2023-2024學(xué)年第二學(xué)期期末試卷
- 阿克蘇工業(yè)職業(yè)技術(shù)學(xué)院《礦山供電技術(shù)課程設(shè)計(jì)》2023-2024學(xué)年第二學(xué)期期末試卷
- 福建農(nóng)林大學(xué)金山學(xué)院《RPA的財(cái)務(wù)應(yīng)用》2023-2024學(xué)年第二學(xué)期期末試卷
- 黑龍江三江美術(shù)職業(yè)學(xué)院《數(shù)字信號(hào)處理器原理及應(yīng)用》2023-2024學(xué)年第二學(xué)期期末試卷
- 泰山學(xué)院《現(xiàn)代管理學(xué)概論》2023-2024學(xué)年第二學(xué)期期末試卷
- 遂寧工程職業(yè)學(xué)院《審計(jì)模擬實(shí)訓(xùn)》2023-2024學(xué)年第二學(xué)期期末試卷
- 鷹潭職業(yè)技術(shù)學(xué)院《電路與電子學(xué)基礎(chǔ)》2023-2024學(xué)年第二學(xué)期期末試卷
- 貴陽(yáng)康養(yǎng)職業(yè)大學(xué)《建筑安全技術(shù)與原理》2023-2024學(xué)年第二學(xué)期期末試卷
- 哈爾濱工業(yè)大學(xué)《嵌入式操作系統(tǒng)實(shí)驗(yàn)》2023-2024學(xué)年第二學(xué)期期末試卷
- 2023版毛概課后答案
- 國(guó)家開(kāi)放大學(xué)《社區(qū)護(hù)理學(xué)(本)》形考任務(wù)1-5參考答案
- 220千伏線(xiàn)路無(wú)人機(jī)放線(xiàn)施工組織設(shè)計(jì)
- (完整版)培訓(xùn)學(xué)校電話(huà)話(huà)術(shù)(初中)
- 注塑模具標(biāo)準(zhǔn)成型條件表
- 施工進(jìn)度計(jì)劃網(wǎng)絡(luò)圖及橫道圖
- 大貓英語(yǔ)分級(jí)閱讀 二級(jí)2 Let's go shopping 課件
- 《中國(guó)文化概論》課程教學(xué)大綱.docx
- 化妝品注冊(cè)注銷(xiāo)申請(qǐng)表
- 建筑物及構(gòu)筑物拆除質(zhì)量控制措施
- BF——2008——0603 北京市房屋租賃合同
評(píng)論
0/150
提交評(píng)論