-PythonWeb開發(fā)技術(shù)與應(yīng)用(Flask版)(微課版)-PPT 第五章 使用數(shù)據(jù)庫存儲內(nèi)容_第1頁
-PythonWeb開發(fā)技術(shù)與應(yīng)用(Flask版)(微課版)-PPT 第五章 使用數(shù)據(jù)庫存儲內(nèi)容_第2頁
-PythonWeb開發(fā)技術(shù)與應(yīng)用(Flask版)(微課版)-PPT 第五章 使用數(shù)據(jù)庫存儲內(nèi)容_第3頁
-PythonWeb開發(fā)技術(shù)與應(yīng)用(Flask版)(微課版)-PPT 第五章 使用數(shù)據(jù)庫存儲內(nèi)容_第4頁
-PythonWeb開發(fā)技術(shù)與應(yīng)用(Flask版)(微課版)-PPT 第五章 使用數(shù)據(jù)庫存儲內(nèi)容_第5頁
已閱讀5頁,還剩77頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

講師:李粵平Flask課程——第五章使用數(shù)據(jù)庫存儲內(nèi)容掌握控制臺與Flask交互的方法掌握Flask-SQLAlchemy數(shù)據(jù)庫框架的基本使用方法掌握Flask-Migrate對數(shù)據(jù)庫進行遷移的方法學(xué)習目標Flask-SQLAlchemySQL數(shù)據(jù)庫簡介Flask-ScriptFlask-Migrate小結(jié)SQL數(shù)據(jù)庫簡介01概念介紹SQL數(shù)據(jù)庫是什么?結(jié)構(gòu)化查詢語言(StructuredQueryLanguage,SQL)專門為了數(shù)據(jù)庫查詢而設(shè)計,用于存取數(shù)據(jù),查詢、更新和管理數(shù)據(jù)庫。SQL數(shù)據(jù)庫通常是一種關(guān)系數(shù)據(jù)庫,這種數(shù)據(jù)庫通常會將數(shù)據(jù)存儲在一個個數(shù)據(jù)表(表格)中。數(shù)據(jù)表的每一個字段(表格列)都是固定的,每一個對象的數(shù)據(jù)都映射到數(shù)據(jù)表的每一條記錄(表格行)中。概念介紹為什么要用SQL數(shù)據(jù)庫?提供用戶注冊、文章發(fā)布等功能的網(wǎng)站都需要存儲數(shù)據(jù),在需要存儲數(shù)據(jù)的情況下便需要使用數(shù)據(jù)庫。通常情況下,數(shù)據(jù)庫將按照一定規(guī)則來存儲數(shù)據(jù),這些規(guī)則使得數(shù)據(jù)變得規(guī)范化,相較于文件、目錄方式存儲更便于管理,且大部分的主流數(shù)據(jù)庫在Flask中都具備完善的解決方案。概念解釋后面主要用ORM框架對數(shù)據(jù)庫操作,不直接使用SQL語句。所以不對sql的基礎(chǔ)語句做過多講解。為什么不直接用SQL語句呢,原因在于,在以往的學(xué)習sql的內(nèi)容時,實現(xiàn)每一個需求都需要建立一條SQL語句。實際項目通常由很多個模塊組合在一起,假設(shè)每一個模塊都跟一個單獨的數(shù)據(jù)表關(guān)聯(lián),那么則需要為每一個模塊編寫多條基本的增、刪、改、查語句,不便于維護。雖然Python對這些SQL語句進行封裝并將其作為函數(shù)使用。這種做法雖然減少了SQL語句的編寫量,但不便于進行復(fù)雜操作,且存在顯著的安全性問題,容易被SQL注入。這時,使用對象關(guān)系映射(ObjectRelationalMapping,ORM)框架可以很好地解決這個問題。ORM框架可以將數(shù)據(jù)映射到對象當中,且對SQL語句的生成進行了高度的封裝,能滿足絕大部分的常見需求,要實現(xiàn)數(shù)據(jù)的增、刪、改、查,僅需操作相應(yīng)對象的屬性即可。接下來,本章將基于Flask-SQLAlchemy(ORM框架),以SQLite數(shù)據(jù)庫為例,對數(shù)據(jù)庫操作進行講解。依賴安裝安裝SQLiteStudioSQLiteStudio是一款開源免費的SQLite數(shù)據(jù)庫可視化工具,簡單易用。讀者可以在SQLiteStudio的官網(wǎng)中下載SQLiteStudio,如下圖所示。依賴安裝下載完成后,保持默認選項設(shè)置進行安裝即可,如下圖所示。SQLiteStudio是一款開源免費的SQLite數(shù)據(jù)庫可視化工具,簡單易用。讀者可以在SQLiteStudio的官網(wǎng)中下載SQLiteStudio,如下圖所示。依賴安裝安裝完場后如下圖所示。后面會用這個工具進行數(shù)據(jù)展示。Flask-Script02“Flask-Script是Flask框架的一個擴展,它提供了一個命令行工具,用于在Flask應(yīng)用中管理和運行各種命令。它可以幫助開發(fā)者執(zhí)行一系列任務(wù),如啟動開發(fā)服務(wù)器、數(shù)據(jù)庫遷移、數(shù)據(jù)庫初始化、腳本運行等,而不必在終端中手動輸入Python代碼。什么是Flask-Script?”概念介紹安裝依賴與安裝Flask的操作一致,打開命令提示符窗口,輸入以下命令。pipinstallflask-script==2.0.6執(zhí)行上述命令之后,能看到“Successfullyinstalled…”提示信息,沒有提示紅色的報錯信息,即安裝成功,此時,F(xiàn)lask-Script的依賴包便安裝完成了,如下圖所示。托管應(yīng)用在之前編寫的例子中,只要執(zhí)行app.py文件,F(xiàn)lask應(yīng)用就開始運行了,無法進行其他操作。如果需要為應(yīng)用添加啟動選項,如添加命令用于清除緩存、添加管理員等其他操作,則需要使用Flask-Script中的Manager對應(yīng)用進行托管。Manager可以根據(jù)用戶輸入的啟動選項(命令)進行不同的操作,在注冊命令之前,需要對Manager進行初始化。代碼如下所示。fromflaskimportFlaskfromflask_scriptimportManager

app=Flask(__name__)

#……其他初始化代碼(Bootstrap等其他內(nèi)容)……

#……視圖函數(shù)代碼……

#使用flask_script提供的Manager()對app進行托管manager=Manager(app)

if__name__=='__main__':#將原來直接運行app的代碼更改為從manager運行manager.run()托管應(yīng)用以下是通過命令行啟動的步驟。(1)獲取項目所在位置,將鼠標指針指向項目位置,單擊鼠標右鍵,在快捷菜單中選擇“CopyPath”選項,復(fù)制路徑,如下圖所示。托管應(yīng)用(2)打開命令提示符窗口,輸入“cd[路徑]”,如下圖所示,此處的[路徑]可以通過粘貼命令得到,如果項目所在盤符不為“C:”,如項目部署于D盤,則需要輸入“D:”后再操作。托管應(yīng)用(3)輸入“pythonapp.py”可啟動對應(yīng)的Flask項目,如下圖所示。此時可以看到,不加參數(shù)啟動會輸出幫助信息,同時,圖中的“positionalarguments”下的內(nèi)容在默認情況下是可以被執(zhí)行的命令。shell命令可以進入交互Shell,而runserver命令的作用則相當于平時單擊按鈕運行應(yīng)用。托管應(yīng)用在前面的操作中,常有需要在命令提示符窗口中操作的過程。在PyCharm中,為了簡化操作,可以單擊“Terminal”按鈕快速打開命令提示符窗口使用此方法打開命令提示符窗口將直接進入項目目錄,推薦使用該方法注冊命令在前面的操作中,介紹了如何通過Flask-Script提供的Manager托管應(yīng)用,這個小節(jié)演示如何注冊命令,并通過命令完成與應(yīng)用的交互。以下是一段簡單的演示代碼。#注冊命令到manager@manddeftest():print('這是一個測試用的命令')與視圖函數(shù)相似,此處使用mand裝飾器對test()函數(shù)進行修飾,輕而易舉地完成了命令的注冊。注冊命令效果如下圖所示。如果要實現(xiàn)其他業(yè)務(wù)邏輯,僅需要將代碼修改成相應(yīng)的代碼即可。shell示例圖創(chuàng)建交互Shell在前面的例子中,使用Manager托管應(yīng)用之后,如果不加參數(shù)運行,可在命令列表中見到shell命令。當執(zhí)行shell命令之后,將會進入當前項目環(huán)境的Python交互Shell。運行交互Shell之后可以見到左邊的輸入提示變成了“>>>”,此時可以輸入Python代碼。但在這個環(huán)境中,僅包含了Flask應(yīng)用實例,不帶其他上下文環(huán)境變量。如果需要訪問其他內(nèi)容進行交互,則需要為Shell實例添加上下文環(huán)境變量。代碼如下所示。fromflask_scriptimportManager,Shellapp=Flask(__name__)manager=Manager(app)#此處users變量需要在Shell環(huán)境中直接訪問users=['Bill','Hunter','Carlos']#該函數(shù)用于創(chuàng)建Shell上下文,將對象注冊到Shell(類似于環(huán)境變量)defmake_shell_context():returndict(users=users,)manager.add_command("shell",Shell(make_context=make_shell_context))創(chuàng)建交互Shell此時在Shell環(huán)境中即可直接訪問users變量,如下圖所示。Flask-SQLAlchemy03“SQLAlchemy是Python下非常好的ORM框架,支持使用MySQL、PostgreSQL、SQLite等主流數(shù)據(jù)庫。Flask-SQLAlchemy基于SQLAlchemy對Flask進行了適配,使其在Flask下的使用變得簡單。什么是Flask-SQLAlchemy?”概念介紹安裝依賴與安裝Flask的操作一致,打開命令提示符窗口,輸入以下命令。pipinstallflask-sqlalchemy==2.4.1執(zhí)行上述命令之后,能看到“Successfullyinstalled…”提示信息,沒有提示紅色的報錯信息,即安裝成功,此時,F(xiàn)lask-SQLAlchemy的依賴包便安裝完成了,如下圖所示。建立模型在建立模型之前,需要對客戶需求進行分析。假設(shè)現(xiàn)在需要實現(xiàn)一個簡單的文章發(fā)布系統(tǒng),用戶可以在其中發(fā)布文章,管理用戶可管理(增、刪、改、查)所有文章。此處可以將以上需求分解為“用戶模塊”與“文章模塊”,然后為各個模塊設(shè)計相應(yīng)的模型。如果需要實現(xiàn)基本的登錄功能,則用戶模型需要擁有“用戶名”“密碼”這些屬性。用戶還可以作為管理員,為了區(qū)分普通用戶和管理員,用戶模型還需要擁有“是否為管理員”屬性。另外,用戶需要創(chuàng)建文章時用戶模型便需要使用“id”屬性與文章模型進行關(guān)聯(lián)。用戶模型的結(jié)構(gòu)如表如下表所示。模型屬性Python中數(shù)據(jù)類型數(shù)據(jù)表中字段類型說明idintINTEGER用于指向用戶的唯一編號usernamestrVARCHAR用戶名passwordstrVARCHAR密碼is_adminboolBOOLEAN是否為管理員建立模型與用戶模型同理,根據(jù)功能將文章模型所需的屬性提煉出來。文章模型的結(jié)構(gòu)如表下表所示模型屬性Python中數(shù)據(jù)類型數(shù)據(jù)表中字段類型說明idintINTEGER用于指向文章的唯一編號titlestrVARCHAR文章標題contentstrVARCHAR文章正文內(nèi)容is_adminboolBOOLEAN是否為管理員建立模型完成了模型的設(shè)計就需要把它轉(zhuǎn)化為代碼,我們首先要初始化Flask-SQLAlchemy,代碼如下。fromflask_sqlalchemyimportSQLAlchemyimportos

#設(shè)置數(shù)據(jù)庫存儲位置basedir=os.path.abspath(os.path.dirname(__file__))app.config['SQLALCHEMY_DATABASE_URI']='sqlite:///'+os.path.join(basedir,'data.sqlite')app.config['SQLALCHEMY_TRACK_MODIFICATIONS']=False

#flask_sqlalchemy初始化代碼db=SQLAlchemy(app)db.init_app(app)在Flask-SQLAlchemy中,通常情況下,所有模型都需要繼承自“db.Model”。SQLAlchemy默認會追蹤對象的修改并發(fā)送信號,但在大多數(shù)情況下,這可能不是必需的。通過將SQLALCHEMY_TRACK_MODIFICATIONS設(shè)置為False,可以關(guān)閉對修改的追蹤。建立模型接著是用戶模型和文章模型的定義。代碼如下classUserModel(db.Model):__tablename__='user'id=db.Column(db.INTEGER,primary_key=True,autoincrement=True)username=db.Column(db.VARCHAR,unique=True)password=db.Column(db.VARCHAR)is_admin=db.Column(db.BOOLEAN,default=False,nullable=False)classArticleModel(db.Model):__tablename__='article'id=db.Column(db.INTEGER,primary_key=True)title=db.Column(db.VARCHAR)content=db.Column(db.VARCHAR)建立模型模型類定義完成后開始初始化數(shù)據(jù)庫文件。此時需要使用5.2.4小節(jié)介紹的交互Shell進行操作,需要注冊交互模型、SQLAlchemy實例(即db對象)到Shell上下文環(huán)境中。關(guān)鍵代碼如下。defmake_shell_context():returndict(db=db,UserModel=UserModel,ArticleModel=ArticleModel,)#主要就是創(chuàng)建Shell上下文,將對象注冊到Shell(類似于環(huán)境變量),只需要在初始化flask-sqlalchemy代碼后定義兩個模型,接著初始化數(shù)據(jù)庫文件就好了。建立模型在命令提示符窗口(終端)中執(zhí)行以下代碼。pythonapp.pyshell進去了shell后再執(zhí)行以下代碼。#根據(jù)已加載的模型創(chuàng)建相應(yīng)數(shù)據(jù)表db.create_all()此時,項目目錄中將會創(chuàng)建一個名為“data.sqlite”的數(shù)據(jù)庫文件,如下圖所示。建立模型使用可視化工具查看該數(shù)據(jù)庫中user表和article表的表結(jié)構(gòu),如下圖所示。建立模型使用可視化工具查看該數(shù)據(jù)庫中user表和article表的表結(jié)構(gòu),如下圖所示。模型及相應(yīng)的數(shù)據(jù)表建立完成后,就到了數(shù)據(jù)操作的講解。數(shù)據(jù)操作前文提到數(shù)據(jù)庫操作主要通過SQL語句進行,而SQLAlchemy提供了將數(shù)據(jù)映射到對象中的操作方式。這樣的方式使得對數(shù)據(jù)的操作變得簡單,使用者無須學(xué)習SQL語法即可完成數(shù)據(jù)操作。就簡單來講就是學(xué)習用SQLAlchemy來實現(xiàn)增刪查改接下來的操作將在交互Shell中進行,首先需要在命令提示符窗口中啟動Shell數(shù)據(jù)操作1.添加數(shù)據(jù)在添加數(shù)據(jù)之前,需要創(chuàng)建相應(yīng)的對象。以用戶模型為例,實際上,添加用戶到數(shù)據(jù)表中,即用戶注冊。以下是代碼(交互Shell)演示。#創(chuàng)建用戶對象user_1=UserModel(username='admin',password='123456',is_admin=True,)

user_2=UserModel(username='user',password='123456',is_admin=False,)到這里還沒有把數(shù)據(jù)存放到數(shù)據(jù)庫中,只是單純創(chuàng)建了。數(shù)據(jù)操作對象創(chuàng)建之后,并沒有立刻存放到數(shù)據(jù)庫中。接下來需要將用戶對象添加到數(shù)據(jù)操作會話中,由SQLAlchemy解析會話中各對象相應(yīng)的操作,并將操作提交到數(shù)據(jù)庫中執(zhí)行。代碼如下。#將用戶對象添加到數(shù)據(jù)操作隊列db.session.add(user_1)db.session.add(user_2)#提交更改到數(shù)據(jù)庫mit()完成以上操作以后,就可以在數(shù)據(jù)庫中查詢到相應(yīng)的數(shù)據(jù),效果如下圖所示。數(shù)據(jù)操作2.查詢數(shù)據(jù)前面使用可視化工具可以方便地查看所有的數(shù)據(jù),但如果需要在Python中獲取相應(yīng)的用戶數(shù)據(jù),則需要通過模型類查詢來實現(xiàn)。如果要實現(xiàn)用戶登錄,便只需要將用戶輸入數(shù)據(jù)與數(shù)據(jù)庫中查詢到的用戶數(shù)據(jù)進行比較,正確則登錄成功,反之登錄失敗。數(shù)據(jù)操作以下是模型類查詢的代碼(交互Shell)演示。#獲取所有用戶對象users=UserModel.query.all()print(users)#獲取所有符合條件的用戶對象users=UserModel.query.filter_by(is_admin=True).all()print(users)#獲取所有符合條件的用戶對象的數(shù)量num=UserModel.query.filter_by(is_admin=True).count()print(num)#獲取一個符合條件的用戶對象user=UserModel.query.filter(UserModel.id>1).first()print(user)以上是一些常見的查詢方法,運行結(jié)果如下所示。

[<UserModel1>,<UserModel2>]

[<UserModel1>]

1

<UserModel2>數(shù)據(jù)操作輸出模型對象無法展示其包含的數(shù)據(jù),要展示模型對象包含的數(shù)據(jù),輸出模型對象相應(yīng)的屬性即可,在Shell中的運行結(jié)果如下所示。>>>print(user.id)2>>>print(user.username)user>>>print(user.password)123456>>>print(user.is_admin)False數(shù)據(jù)操作逐個屬性輸出數(shù)據(jù)始終不便于操作,為了更方便進行接下來的數(shù)據(jù)展示操作,在此建立一個模型基類,用于重寫模型輸出時的格式(可選操作)。定義模型基類要分幾個步驟,首先是定義所有模型的基類是什么,然后要定義模型的初始化方法,再然后就是定義對象要輸出的格式。那么我們先按照定義模型的基類為始,接著是定義模型初始化方法,代碼如下:#定義所有模型的基類classBaseModel(Model):#聲明query屬性的類型,以獲得代碼提示補全query:BaseQuery#定義模型初始化方法def__init__(self,**kwargs):#將參數(shù)傳入父類初始化方法super(BaseModel,self).__init__(**kwargs)這個__init__方法是模型基類的初始化方法。它通過調(diào)用父類的初始化方法來傳遞參數(shù)。數(shù)據(jù)操作最后是定義輸出格式,代碼如下所示。#定義對象輸出格式,方便輸出預(yù)覽def__repr__(self):fields=[]

#獲取對象原始數(shù)據(jù)fork,vinself.__dict__.items():#只輸出相關(guān)屬性ifk[0]!='_':#防止模型關(guān)聯(lián)后無限遞歸ifisinstance(v,BaseModel):fields.append('%s=<%s...>'%(k,v.__class__.__name__))elifisinstance(v,str):fields.append("%s='%s'"%(k,v))else:fields.append('%s=%a'%(k,v))

#拼接顯示結(jié)果result='<%s%s>'%(self.__class__.__name__,''.join(fields))returnresult在__repr__方法中,這部分代碼遍歷對象的屬性和屬性值,并根據(jù)不同情況構(gòu)建輸出的字段。如果屬性值是另一個繼承自BaseModel的對象,它會顯示對象類型和占位符。如果屬性值是字符串,它會顯示屬性名和字符串值。否則,它會使用%a格式顯示屬性名和屬性值。數(shù)據(jù)操作然后修改各模型的繼承,例如為用戶模型添加模型基類的繼承。代碼如下。classUserModel(db.Model,BaseModel):__tablename__='user'id=db.Column(db.INTEGER,primary_key=True,autoincrement=True)username=db.Column(db.VARCHAR,unique=True)password=db.Column(db.VARCHAR)is_admin=db.Column(db.BOOLEAN,default=False,nullable=False)然后再執(zhí)行前面的查詢代碼,可以得出以下結(jié)果。[<UserModelusername='admin'password='123456'is_admin=Trueid=1>,<UserModelusername='user'password='123456'is_admin=Falseid=2>][<UserModelusername='admin'password='123456'is_admin=Trueid=1>]1<UserModelusername='user'password='123456'is_admin=Falseid=2>這樣可以在一定程度上更方便地查看模型中所包含的數(shù)據(jù)。數(shù)據(jù)操作3.修改數(shù)據(jù)修改數(shù)據(jù)的操作建立于查詢數(shù)據(jù)的基礎(chǔ)之上。獲取到模型對象后,為對象屬性進行賦值,再將模型對象加入數(shù)據(jù)操作隊列,執(zhí)行提交進行改動即可。代碼如下所示。在數(shù)據(jù)庫查詢的結(jié)果如下圖所示。#獲取id為2的用戶對象,并提交更改到數(shù)據(jù)庫user=UserModel.query.get(2)#type:UserModeluser.password='admin'user.is_admin=Truedb.session.add(user)mit()數(shù)據(jù)操作4.刪除數(shù)據(jù)刪除數(shù)據(jù)的操作亦是建立于查詢數(shù)據(jù)基礎(chǔ)之上的,在獲取到模型對象后,將模型對象加入數(shù)據(jù)操作隊列,執(zhí)行提交進行改動即可。不同之處在于刪除使用delete()方法進行操作。代碼如下所示。在數(shù)據(jù)庫查詢的結(jié)果如下圖所示。#獲取特定id的用戶對象,并將其從數(shù)據(jù)庫中刪除user_1=UserModel.query.get(1)#type:UserModeluser_2=UserModel.query.get(2)#type:UserModeldb.session.delete(user_1)db.session.delete(user_2)mit()高級查詢高級查詢可以獲取特定位置/數(shù)量的數(shù)據(jù)、對數(shù)據(jù)進行排序、字符串包含判斷,以及復(fù)合條件查詢(and/or)的操作。這一塊簡單講書上的例子,其他就不細說。大家感興趣可以把其他例子的結(jié)果也輸出出來看一看。首先使用之前創(chuàng)建的文章模型進行演示。在操作之前,需要添加一些測試數(shù)據(jù),在交互Shell中執(zhí)行以下代碼。#快速添加5個測試用的文章模型foriinrange(5):article=ArticleModel(title='文章_%d'%i,content='Thisisarticle_%d.'%i)db.session.add(article)article=ArticleModel(title='測試文章1',content='HelloWorld!')db.session.add(article)article=ArticleModel(title='測試文章2',content='HelloFlask!')db.session.add(article)mit()高級查詢執(zhí)行后的效果如數(shù)據(jù)庫內(nèi)容如下圖所示。高級查詢這里執(zhí)行第一個查詢代碼,代碼如下#從第3個對象(索引從0開始)開始,獲取所有數(shù)據(jù)articles=ArticleModel.query.offset(2).all()print(articles)查詢效果圖如下所示。大家感興趣可以把書本其他的查詢也執(zhí)行一邊看看效果如何。模型關(guān)聯(lián)一提到數(shù)據(jù)庫,就會想到表關(guān)聯(lián),那么SQLAlchemy也是一樣的,拿前面的章節(jié)舉例,建立了兩個模型:一個是用戶模型,另一個是文章模型。我們知道在網(wǎng)站使用流程中,文章由用戶創(chuàng)建,即每一個文章對象都會對應(yīng)一個作者;可以根據(jù)文章作者找到對應(yīng)的用戶,也可以根據(jù)特定的用戶查詢到與之對應(yīng)的文章。那么如果想實現(xiàn)以上效果的話,僅需為這兩個模型建立外鍵關(guān)聯(lián)。一個是在文章模型代碼中添加外鍵(作者id),一個是反向關(guān)聯(lián)屬性(用戶模型中定義)模型關(guān)聯(lián)首先是文章模型代碼中添加外鍵(作者id),代碼如下。classArticleModel(db.Model,BaseModel):__tablename__='article'

id=db.Column(db.INTEGER,primary_key=True)title=db.Column(db.VARCHAR)content=db.Column(db.VARCHAR)

#此處根據(jù)作者(用戶)id與文章模型進行外鍵關(guān)聯(lián)#作者(用戶)id不為主鍵,為了保證查詢效率,需要為字段建立索引(index=True)author_id=db.Column(db.INTEGER,db.ForeignKey(UserModel.id),index=True)

#在UserModel中建立一對多關(guān)聯(lián)時,為ArticleModel添加了反向關(guān)聯(lián)屬性#此處為ArticleModel聲明author屬性類型,以便于IDE進行識別author:UserModel模型關(guān)聯(lián)其次是在用戶模型中建立反向關(guān)聯(lián),代碼如下。classUserModel(db.Model,BaseModel):id=db.Column(db.INTEGER,primary_key=True,autoincrement=True)username=db.Column(db.VARCHAR,unique=True)password=db.Column(db.VARCHAR)is_admin=db.Column(db.BOOLEAN,default=False,nullable=False)#建立一對多映射關(guān)系(uselist=True)#為了便于IDE識別變量類型,此處聲明articles類型為listarticles:list=db.relationship('ArticleModel',backref='author',uselist=True)模型關(guān)聯(lián)此時,模型結(jié)構(gòu)相較于之前的數(shù)據(jù)表發(fā)生了改變,需要重新創(chuàng)建數(shù)據(jù)表,并添加相關(guān)測試數(shù)據(jù)。代碼如下。#重建所有已加載模型的數(shù)據(jù)表db.drop_all()db.create_all()#創(chuàng)建用戶對象user_1=UserModel(username='admin',password='123456',is_admin=True,)user_2=UserModel(username='user',password='123456',is_admin=False,)#將用戶對象提交到數(shù)據(jù)操作隊列db.session.add(user_1)db.session.add(user_2)#提交更改到數(shù)據(jù)庫mit()模型關(guān)聯(lián)接下來就是用兩種不同的方式添加文章,(交互Shell)代碼如下。#根據(jù)用戶模型關(guān)聯(lián)屬性進行文章添加user_1=UserModel.query.get(1)#type:UserModeluser_1.articles.append(ArticleModel(title='文章_1',content='nomessage.'))db.session.add(user_1)#根據(jù)文章模型反向關(guān)聯(lián)屬性與用戶進行關(guān)聯(lián)并添加文章user_2=UserModel.query.get(2)article=ArticleModel(title='文章_2',content='nomessage.')article.author=user_2db.session.add(article)mit()兩種方式的區(qū)別有兩點,1、關(guān)聯(lián)屬性的方向;2、賦值方式關(guān)聯(lián)屬性的方向:第一種方式是通過用戶模型的關(guān)聯(lián)屬性向文章模型添加數(shù)據(jù)。第二種方式是通過文章模型的反向關(guān)聯(lián)屬性向用戶模型添加數(shù)據(jù)。賦值方式:第一種方式通過列表的append方法將文章實例添加到用戶的關(guān)聯(lián)屬性中。第二種方式通過直接賦值將用戶實例賦給文章的反向關(guān)聯(lián)屬性。模型關(guān)聯(lián)優(yōu)缺點:第一種方式:優(yōu)點:代碼簡潔,直觀地通過關(guān)聯(lián)屬性添加數(shù)據(jù)。缺點:如果關(guān)聯(lián)屬性的列表較長,添加多個文章可能會導(dǎo)致多次數(shù)據(jù)庫查詢,效率較低。第二種方式:優(yōu)點:可以在不加載整個關(guān)聯(lián)屬性列表的情況下,直接將用戶與文章關(guān)聯(lián)。適用于關(guān)聯(lián)屬性較大的情況。缺點:代碼稍微復(fù)雜,需要設(shè)置反向關(guān)聯(lián)屬性。根據(jù)具體需求,可以選擇適合應(yīng)用程序和數(shù)據(jù)模型的添加方式。如果關(guān)聯(lián)屬性較小且不太頻繁變動,第一種方式可能更為直觀和便捷。如果關(guān)聯(lián)屬性較大或需要更高的效率,第二種方式可能更適合。模型關(guān)聯(lián)在數(shù)據(jù)庫里的效果圖如下所示。模型關(guān)聯(lián)然后在shell中展示文章模型數(shù)據(jù)。代碼如下所示。>>>print(user_1.articles)[<ArticleModelid=1content='nomessage.'author_id=1title='文章_1'>]>>>article=user_2.articles[0]>>>print(article)<ArticleModeltitle='文章_2'content='nomessage.'author_id=2id=2author=<UserModel...>>>>>print(article.author)<UserModelusername='user'password='123456'is_admin=Falseid=2articles=[<ArticleModeltitle='\u6587\u7ae0_2'content='nomessage.'author_id=2id=2author=<UserModel...>>]>以上便是用戶模型與文章模型簡單的一對多關(guān)聯(lián)的實現(xiàn)。此時,再來回顧前面所設(shè)計的用戶模型,這個模型僅包含了用戶名、密碼、是否為管理員3個基本屬性(字段),這個模型其實僅用于用戶賬號驗證。模型關(guān)聯(lián)在開發(fā)的情況中,難免會遇到需要增加需求,需要擴展數(shù)據(jù)庫的關(guān)聯(lián)信息。我們還可以用一種方法,一對一關(guān)聯(lián)。如果現(xiàn)在需要對每一個用戶添加一個對應(yīng)的性別、介紹等多項信息,我們可以創(chuàng)建用戶信息模型,并與用戶模型進行一對一關(guān)聯(lián)實現(xiàn)。這樣做可以在不修改用戶模型的情況下,為用戶擴展信息展示功能。用戶模型類定義的代碼如下classUserInfoModel(db.Model,BaseModel):__tablename__='user_info'

#由于在UserModel中建立了映射關(guān)系,在backref參數(shù)中使用"user"屬性進行反向關(guān)聯(lián)#為了便于代碼編寫,需要在此處聲明關(guān)聯(lián)屬性類型user:UserModel

#設(shè)置外鍵,根據(jù)UserModel的id字段進行關(guān)聯(lián)user_id=db.Column(db.INTEGER,db.ForeignKey(UserModel.id),primary_key=True)sex=db.Column(db.INTEGER)introduce=db.Column(db.TEXT)模型關(guān)聯(lián)用戶信息模型建立完成后,需要在用戶模型中建立反向關(guān)聯(lián),代碼如下所示。classUserModel(db.Model,BaseModel):id=db.Column(db.INTEGER,primary_key=True,autoincrement=True)username=db.Column(db.VARCHAR,unique=True)password=db.Column(db.VARCHAR)is_admin=db.Column(db.BOOLEAN,default=False,nullable=False)#建立一對一映射關(guān)系(uselist=False)#backref參數(shù)用于在UserInfoModel的"user"屬性中建立反向關(guān)聯(lián)#cascade參數(shù)用于關(guān)聯(lián)模型操作,如刪除UserModel對象時,同時刪除相應(yīng)的UserInfoModel對象info=db.relationship('UserInfoModel',backref='user',uselist=False,cascade='all')模型關(guān)聯(lián)接下來通過3種不同方式創(chuàng)建用戶并設(shè)置用戶信息,以下是代碼(交互Shell)演示。#由于前面建立了新的模型,所以在操作數(shù)據(jù)前需要創(chuàng)建相應(yīng)數(shù)據(jù)表db.create_all()#與使用普通方式創(chuàng)建模型一致,在構(gòu)造參數(shù)中關(guān)聯(lián)信息模型user_3=UserModel(username='test',password='123456',is_admin=False,info=UserInfoModel(sex=1,introduce='Thisisuser3.'),)首先是第一種,代碼如下所示。優(yōu)點:這種方式直接在用戶模型的構(gòu)造函數(shù)中傳遞了關(guān)聯(lián)信息模型的實例,代碼簡潔,一次性完成了模型之間的關(guān)聯(lián)。缺點:如果需要構(gòu)建多個用戶并分別關(guān)聯(lián)不同的信息模型,需要多次重復(fù)這種方式,可能不夠靈活。模型關(guān)聯(lián)#創(chuàng)建用戶模型后,通過設(shè)置屬性關(guān)聯(lián)用戶信息模型user_4=UserModel(username='master',password='123456',is_admin=False,)user_4.info=UserInfoModel(sex=1,introduce='Thisisuser4.')接著是第二種,代碼如下所示。優(yōu)點:這種方式先創(chuàng)建了用戶模型,然后通過設(shè)置屬性的方式關(guān)聯(lián)信息模型,更加靈活,可以在不同時間點建立關(guān)聯(lián)。缺點:需要額外的代碼來設(shè)置屬性,相對于第一種方式稍微繁瑣一些。模型關(guān)聯(lián)最后是第三種,代碼如下所示。#創(chuàng)建用戶信息模型后,通過反向關(guān)聯(lián)的方式關(guān)聯(lián)用戶模型user_5=UserModel(username='slave',password='123456',is_admin=False,)UserInfoModel(sex=2,introduce='Thisisuser5.').user=user_5優(yōu)點:這種方式創(chuàng)建了信息模型,并通過反向關(guān)聯(lián)的方式將用戶模型與信息模型關(guān)聯(lián),也具有一定的靈活性。缺點:可能相對不太直觀,需要了解數(shù)據(jù)庫模型之間的關(guān)系,不如前兩種方式容易理解。模型關(guān)聯(lián)然后就是需要把用戶添加的信息傳遞到數(shù)據(jù)庫里面。代碼如下所示。數(shù)據(jù)庫的內(nèi)容如下圖所示。db.session.add(user_3)db.session.add(user_4)db.session.add(user_5)mit()由于以前創(chuàng)建的用戶并沒有關(guān)聯(lián)用戶信息,故此處的用戶信息數(shù)據(jù)表不包含admin用戶與user用戶的信息。以上便是模型一對一關(guān)聯(lián)的實現(xiàn)。模型關(guān)聯(lián)對于前面三種添加用戶信息的方法,選擇哪種方法取決于具體需求和代碼的清晰度。第一種方法適合一次性建立模型關(guān)聯(lián),第二種方法適合在不同時間點建立關(guān)聯(lián),第三種方法則具有一定的靈活性,但可能需要更多的了解數(shù)據(jù)庫模型的關(guān)系。在實際應(yīng)用中,可以根據(jù)需求選擇最適合的方式。數(shù)據(jù)分頁功能數(shù)據(jù)分頁顯示是一個很常見的功能。例如之前所設(shè)計的文章模型,當文章數(shù)量達到一定程度(例如10篇)時,便不再適合在單個頁面中展示,這時便需要用到數(shù)據(jù)分頁顯示功能,每一頁加載部分數(shù)據(jù)。當然,像這種常見需求,F(xiàn)lask-SQLAlchemy與Flask-Bootstrap都已經(jīng)實現(xiàn)好了,只要引入相應(yīng)功能并使用即可。以下是數(shù)據(jù)分頁功能視圖函數(shù)的代碼。@app.route('/paginator')defpaginator():#每頁顯示3篇文章pagination=ArticleModel.query.paginate(per_page=3)returnrender_template('paginator.html',pagination=pagination)ArticleModel.query:這是通過SQLAlchemy數(shù)據(jù)庫模型創(chuàng)建的查詢對象,它用于查詢文章模型(ArticleModel)的數(shù)據(jù)庫表。paginate(per_page=3):這是對查詢結(jié)果進行分頁的操作。per_page=3意味著每頁顯示3篇文章。這將返回一個分頁對象(pagination),其中包含了當前頁的文章數(shù)據(jù)以及分頁信息。數(shù)據(jù)分頁功能模板頁面的代碼如下。部分內(nèi)容解釋如右所示。{%extends'bootstrap/base.html'%}{#從Flask-Bootstrap引入分頁功能#}{%import'bootstrap/pagination.html'aspagi%}{%blocktitle%}數(shù)據(jù)分頁顯示{%endblock%}{%blockbody%}<divclass="container">{%foriteminpagination.items%}<h1>{{item.title}}</h1><p>{{item.content|safe}}</p>{%endfor%}{#根據(jù)pagination(分頁)對象渲染分頁按鈕#}{{pagi.render_pagination(pagination)}}</div>{%endblock%}1、使用了Flask-Bootstrap的pagination.html里面的分頁控件。2、{%foriteminpagination.items%}和{%endfor%}:這是一個循環(huán)塊,用于迭代分頁對象(pagination)中的每個項目。在這個循環(huán)中,模板將渲染每篇文章的標題和內(nèi)容。3、<h1>{{item.title}}</h1>和<p>{{item.content|safe}}</p>:這些是用于顯示文章標題和內(nèi)容的模板變量。{{item.title}}和{{item.content|safe}}分別表示當前文章對象(item)的標題和內(nèi)容。|safe過濾器用于確保內(nèi)容以原樣渲染,而不是將其解釋為HTML。4、{{pagi.render_pagination(pagination)}}:這一行代碼調(diào)用Flask-Bootstrap提供的render_pagination函數(shù)來渲染分頁控件。這個函數(shù)接受分頁對象(pagination)作為參數(shù),并生成分頁按鈕,允許用戶瀏覽不同的頁數(shù)。數(shù)據(jù)分頁功能效果圖如下所示。Flask-Migrate04“Flask-Migrate是一個Flask擴展,用于管理FlaskWeb應(yīng)用程序中的數(shù)據(jù)庫遷移(migration)。數(shù)據(jù)庫遷移是一種重要的技術(shù),用于在開發(fā)過程中管理數(shù)據(jù)庫模型的變化,包括創(chuàng)建新的表、修改表結(jié)構(gòu)、添加或刪除列等。什么是Flask-Migrate?”概念介紹“具體來說,F(xiàn)lask-Migrate主要用于以下用途:1、數(shù)據(jù)庫模型的版本控制:Flask-Migrate允許您在應(yīng)用程序的不同版本之間跟蹤數(shù)據(jù)庫模型的變化。每次您修改數(shù)據(jù)庫模型時,您都可以創(chuàng)建一個新的遷移版本。2、數(shù)據(jù)庫遷移的自動生成:Flask-Migrate可以自動生成數(shù)據(jù)庫遷移腳本,這些腳本包含了數(shù)據(jù)庫模型變化的詳細說明,包括添加、修改或刪除表,以及更新表的結(jié)構(gòu)。3、應(yīng)用數(shù)據(jù)庫遷移:使用Flask-Migrate,您可以輕松地將數(shù)據(jù)庫模型的變化應(yīng)用到數(shù)據(jù)庫中。這樣,您可以在開發(fā)過程中保持數(shù)據(jù)庫模型與應(yīng)用的同步,而不會丟失已有的數(shù)據(jù)。4、回滾遷移:如果需要,您還可以回滾遷移,即撤銷之前的遷移操作,以恢復(fù)到之前的數(shù)據(jù)庫狀態(tài)。Flask-Migrate的用途是什么?”概念介紹安裝依賴與安裝Flask的操作一致,打開命令提示符窗口,輸入以下命令。pipinstallflask-migrate==2.5.2執(zhí)行上述命令之后,能看到“Successfullyinstalled…”提示信息,沒有提示紅色的報錯信息,即安裝成功,此時,F(xiàn)lask-Migrate的依賴包便安裝完成了如下圖所示?;静僮髟谑褂肍lask-Migrate之前,需要在Flask-Script提供的Manager對象中添加指令(MigrateCommand),以下是代碼演示。fromflask_migrateimportMigrate,MigrateCommand#創(chuàng)建migrate對象并添加db(數(shù)據(jù)庫migrate)指令migrate=Migrate(app,db)migrate.init_app(app,render_as_batch=True)manager.add_command('db',MigrateCommand)migrate=Migrate(app,db):這一行創(chuàng)建了一個Migrate對象,并將應(yīng)用實例app和數(shù)據(jù)庫實例db傳遞給它。Migrate對象用于管理數(shù)據(jù)庫遷移。migrate.init_app(app,render_as_batch=True):這一行初始化了Migrate對象,并將應(yīng)用實例app傳遞給它。render_as_batch=True表示將遷移操作批量渲染,這是一個性能優(yōu)化選項。初始化后,Migrate對象將與應(yīng)用關(guān)聯(lián),以便在應(yīng)用中執(zhí)行數(shù)據(jù)庫遷移。manager.add_command('db',MigrateCommand):這一行將MigrateCommand命令添加到Flask-Script(或Flask-CLI)的管理命令中。'db'是命令的名稱,可以在終端中使用該名稱來執(zhí)行數(shù)據(jù)庫遷移命令。基本操作此時,在命令提示符窗口中執(zhí)行“pythonapp.py”就可以見到新增了一條名為“db”的指令,如下圖所示?;静僮髟谑褂肍lask-Migrate后,不再需要通過“db.create_all()”或“db.drop_all()”命令,可直接對數(shù)據(jù)庫進行操作。通常情況下,所有對數(shù)據(jù)表的更改操作都可以通過Flask-Migrate進行。由于在此之前使用“db”對象創(chuàng)建了數(shù)據(jù)庫,在演示Flask-Migrate的相關(guān)操作前需要刪除數(shù)據(jù)庫文件,如圖下圖所示。在刪除文件之前,需要關(guān)閉數(shù)據(jù)可視化工具,如SQLiteStudio?;静僮鹘酉聛淼牟僮鲗⒃诿钐崾痉翱谥羞M行。首先是初始化數(shù)據(jù)庫遷移倉庫,使用init子命令進行。C:\Users\User\PycharmProjects\db_inter_active>pythonapp.pydbinitCreatingdirectoryC:\Users\User\PycharmProjects\db_inter_active\migrations...doneCreatingdirectoryC:\Users\User\PycharmProjects\db_inter_active\migrations\versions...doneGeneratingC:\Users\User\PycharmProjects\db_inter_active\migrations\alembic.ini...doneGeneratingC:\Users\User\PycharmProjects\db_inter_active\migrations\env.py...doneGeneratingC:\Users\User\PycharmProjects\db_inter_active\migrations\README...doneGeneratingC:\Users\User\PycharmProjects\db_inter_active\migrations\script.py.mako...donePleaseeditconfigur

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論