第46天:Flask數據持久化


圖片

Web 應用離不開數據存儲,今天就來學習下 Flask 中如何與數據庫交互,最後咱們將作一個提交的實例html

Flask 中最方便用的數據庫框架是 flask_sqlalchamy,是對 SQLAlchamy 在 Flask 中的擴展, SQLAlchemy 是一個 Python 數據庫工具(ORM,即對象關係映射)。python

藉助 SQLAlchemy,經過定義 Python 類來表示數據庫裏的一張表(類屬性表示表中的字段 或者 列),經過對這個類進行各類操做來代替寫 SQL 語句。這個類咱們稱之爲模型類,類中的屬性咱們將稱之爲字段。sql

SQLAlchemy 支持多種數據庫,對於不一樣的數據庫只須要修改下配置連接就能夠,在這裏咱們使用關係型數據庫 SQLite 做爲演示。shell

SQLite 是基於文件的關係型數據庫,不須要單獨啓動數據庫服務器,適合在開發時使用,或是在數據庫操做簡單、訪問量低的程序中使用。數據庫

安裝 flask_sqlalchamy

pip install flask_sqlalchamy

安裝以後,導入到項目中,對應用進行初始化:flask

from flask import Flaskfrom flask_sqlalchamy import SQLAlchamy  # 導入 SQLAlachamy
app = Flask(__name__) # 建立 Flask 應用
db = SQLAlchamy(app) # 初始化應用

設置數據庫鏈接 URI

數據庫通常做爲第三方應用,須要經過創建與數據庫的鏈接,讓應用能夠是使用數據庫。服務器

常見的數據庫有 MySql、SqlServer、Oracle、SQLite、MongoDB 等等,每種數據庫都有本身特定的鏈接格式,咱們使用的是簡單的 SQLite 數據庫,它的鏈接格式是:session

sqlite:////數據庫文件的絕對地址

注意: 若是您使用 Windows 系統,上面的 URI 前綴部分須要寫入三個斜線 (即 sqlite:///)app

在例子中,將數據庫文件路徑設置爲當前應用的根目錄下:框架

import os# ...app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:////' + os.path.join(app.root_path, 'data.db')

注意:  爲了設置 Flask、擴展或是咱們程序自己的一些行爲,須要設置和定義一些配置變量。Flask  提供了一個統一的接口來寫入和獲取這些配置變量:Flask.config  字典。配置變量的名稱必須使用大寫,寫入配置的語句通常會放到擴展類實例化語句以前。app.config 是一種簡便的 Flask 應用的配置方式

模型

模型簡單來講就是數據庫中的一張表定義,須要有名稱,字段,在 Python 中用一個類來表示,因爲須要和數據庫的表對應,模型必須繼承自 SQLAlchamy 的 Model 類

在初始化應用中,咱們獲得一個 SQLAlchamy 的實例 db,定義模型都是繼承自實例的 Model 類的

下面定義一個 Profile 模型,用來記錄一個用戶的基本信息:

class Profile(db.Model):    id = db.Column(db.Integer, primary_key=True) # 主鍵    name = db.Column(db.String(20))    birthday = db.Column(db.Date())    createtime = db.Column(db.DateTime())    about = db.Column(db.Text())
  • 模型中的屬性,都是有 Column 類的一個實例,傳入的參數爲字段的類型,下面的表格列出了經常使用的字段類
  • 在  db.Column() 中添加額外的選項(參數)能夠對字段進行設置。好比,primary_key  設置當前字段是否爲主鍵。除此以外,經常使用的選項還有  nullable(布爾值,是否容許爲空值)、index(布爾值,是否設置索引)、unique(布爾值,是否容許重複值)、default(設置默認值)等
  • 當一個列被設置爲主鍵,默認主鍵值是自增加的

經常使用的字段類型以下表所示:

字段類型 說明
db.Integer 整數
db.String(size) 字符串 size 爲字符串長度
db.DateTime 日期時間
db.Date 日期
db.Text 長文本,能夠存放 CLOB (二進制數據)
db.Float 浮點數字
db.Boolean 布爾值

建立庫表

定義好數據模型以後,能夠用模型來建立數據庫表,即用模型來管理庫表的建立。

若是已經有了數據,能夠經過 sqlacodegen 或者 Flask-SQLAcodegen 工具來由數據庫中庫表定義建立 SQLAlchamy 模型

使用 db.create_all() 能夠將應用中的模型,建立成數據庫中的表,庫表名爲模型名稱的小寫形式。能夠經過 __tablename__ 模型類屬性類指定庫表名稱

通常庫表是在初始化應用時建立,因此不必將建立語句寫在應用中,能夠在庫表定義發生變化是單獨使用 Flask-Shell 工具與數據庫同步一次模型定義

在命令行下,將目錄切換到當前項目根目錄執行:

$ flask shell>>> from app import db # app 對應的是應用主代碼文件名,如app.py>>> db.create_all()

執行完成,就會在在項目根目錄下建立一個 data.db 文件,這個文件是配置中設置的 SQLite 數據庫文件

若是變動了模型定義,能夠先調用 db.drop_all() 來刪除數據庫中表的定義,注意 db.drop_all() 刪除數據庫中表的同時,也會刪除數據

若是須要保留數據,可使用使用數據庫遷移工具,好比集成了 AlembicFlask-Migrate 擴展工具

Flask  Shell 打開的 Python Shell 環境並不等於 用 python 打開的環境,Flask Shell  會將當前目錄下的應用做爲環境上下文,因此在執行 Flask Shell  時須要將命令行當前目錄切換到項目所在的目錄下。項目目錄下,應用主代碼文件應該命名爲 app.py 或者 wsgi.py

增刪改查

爲了方便說明數據庫的使用,咱們還在上面的用 Flask Shell 打開的 Python Shell 環境下執行代碼

新增

向數據庫中新增記錄

from app import Profile # Profile 是在應用中定義的模型from app import dbimport datetime
# 建立一個 Profile 實例profile = Profile()profile.name = "Tiger"# Date 和 DateTime 類型屬性,必須接受 Python datetime 對象profile.birthday = datetime.datetime(2001, 10, 1)profile.createtime = datetime.datetime.now()profile.about = 'My name is Tiger, come from Beijing China.'
db.session.add(profile)  # 將變化添加db.session.commit() # 將變化提交
  • 在 Flash Shell 環境中,先引入 Profile 模型類,而後引入數據庫的實例 db,因爲有些字段是日期類型,還須要引入 datetime 模塊
  • 建立一個 Profile 實例 profile,設置屬性值
  • 將實例 profile 鍵入到會話中
  • 提交會話,在數據庫表 profile 中新增一條記錄

session 是一個與數據庫通訊的會話,是 SQLAlchamy 框架與數據庫交互的代理,若是要放棄某次變化,能夠調用 session.rollback() 回滾掉未提交的變化,這個和數據庫的事務很類似,但和數據庫的事務沒有關係

查詢

能夠經過對模型類的 query 屬性調用可選的過濾方法和查詢方法,獲取到對應的單個或多個記錄(記錄以模型類實例的形式表示)。查詢語句的格式以下:

<模型類>.query.<過濾方法(可選)>.<查詢方法>

例如:

# ... 忽略引入相關代碼profile = Profile.query.first()  # 查詢出 profile 表中第一條記錄
profile.name  # Tigerprofile.birthday # 2001-10-01 00:00:00profile.about  # My name is Tiger, come from Beijing China.profiles = Profile.query.all()  # 查詢出全部記錄,返回 Profile 實例列表profile_count = Profile.query.count()  # 記錄條數profile = Profile.query.get(1)  # 獲取主鍵爲 1 的記錄profile = Profile.filter_by(name='Tiger').first()  # 查詢 name 等於 Tiger 的記錄集中第一條記錄profiles = Profile.filter(Profile.name != 'Tiger').all()  # 查詢 name 不等於 Tiger 的全部記錄
  • 經常使用的過濾方法:
方法名稱 說明
filter() 使用指定的規則過濾記錄,返回新產生的查詢對象
filter_by() 使用指定規則過濾記錄(以關鍵字表達式的形式),返回新產生的查詢對象
order_by() 根據指定條件對記錄進行排序,返回新產生的查詢對象
group_by() 根據指定條件對記錄進行分組,返回新產生的查詢對象
  • 經常使用的查詢方法:
方法名稱 說明
all() 返回包含全部查詢記錄的列表
first() 返回查詢的第一條記錄,若是未找到,則返回None
get(id) 傳入主鍵值做爲參數,返回指定主鍵值的記錄,若是未找到,則返回None
count() 返回查詢結果的數量
first_or_404() 返回查詢的第一條記錄,若是未找到,則返回404錯誤響應
get_or_404(id) 傳入主鍵值做爲參數,返回指定主鍵值的記錄,若是未找到,則返回404錯誤響應
paginate() 返回一個Pagination對象,能夠對記錄進行分頁處理

更新

首先將記錄查詢出來,而後對其進行修改,以後調用 db.session.commit() 提交變動,注意這裏再也不須要調用 db.session.add() 了:

profile = Profile.query.get(1)  # 查詢出ID爲 1 的記錄profile.about = profile.about + ' I like coding~'  # 在簡介中添加些內容db.session.commit()  # 必須調用提交,不然將不會被更新到數據庫

刪除

也須要將記錄查詢出來,調用 db.seeeion.delete(),最後提交

profile = Profile.query.get(1)  # 查詢出ID爲 1 的記錄db.session.delete(profile)  # 刪除記錄db.session.commit()  # 提交變動

若是要批量刪除,須要遍歷結果集用上面方法逐個刪除,也可使用 query 屬性或者 filter 的結果進行刪除:

Profile.query.filter(Profile.name == 'Tom').delete()  # 按照過濾條件來刪除Profile.query.delete()  # 刪除全部記錄db.seesion.commit()  # 提交變動

業務中的處理數據

瞭解了數據庫的基本操做以後,就能夠在業務邏輯中編寫數據庫處理代碼了

定義一個視圖函數,將根據查詢參數來找到對應的 Profile 記錄,而且將該送給顯示模板

@app.route('/myprofile/<id>/')def myprofile(id):    profile = Profile.query.get(id)  # 利用參數 id 讀取數據庫記錄    return render_template('profile.html', profile=profile)  # 將結果送給模板作展現

模板代碼 profile.html

<h1>{{ profile.name }}'s Info </h1><dt>Name:</dt><dd>{{ profile.name }}</dd><dt>Birthday:</dt><dd>{{ profile.birthday }}</dd><dt>About:</dt><dd>{{ profile.about }} </dd>

啓動應用後,訪問 localhost:5000/myprofile/1 就能夠看到 ID 爲 1 的 Profile 信息。

結合前面講述的 Form 知識,在視圖函數中處理表單中提交的內容,並保存的數據庫,下面是視圖函數:

@app.route('/createprofile/', methods=('GET', 'POST'))def createprofile():    form = MyForm()    if form.validate_on_submit():  # 若是表單提交了 用表單數據建立 Profile 對象        profile = Profile()        profile.name = form.name.data        profile.birthday = form.birthday.data        profile.about = form.about.data or ""
       db.session.add(profile)        db.session.commit()        return redirect(url_for('myprofile', id=profile.id))  # 跳轉到展現頁面    else:        return render_template('createprofile.html', form=form)  # 顯示建立頁面

當判斷表單被提交後,用提交數據建立 Profile 對象,存儲到數據庫,而且跳轉到展現頁面。

總結

本節課程簡單介紹了 Flask 中數據庫技術,主要是藉助 Flask-SQLAlchamy 框架來操做數據庫,以 SQLite 關係數據庫爲例講解了數據的增刪改查操做,最後展現瞭如何在視圖函數中操做數據,以便與 Flask 應用相結合。

示例代碼:Python-100-days-day046

參考

  • https://docs.sqlalchemy.org/en/13/core/sqlelement.html
  • https://read.helloflask.com/c5-database
  • https://greyli.com/generate-flask-sqlalchemy-model-class-for-exist-database/
  • https://www.cnblogs.com/shengulong/p/6639581.html

系列文章

    第45天:Web表單

    第44天:Flask 框架集成Bootstrap

    第43天:Python filecmp&difflib模塊

    第42天:Python paramiko 模塊

    第41天:Python operator 模塊

    第0-40天:從0學習Python 0-40合集
相關文章
相關標籤/搜索