咱們能夠在Flask中使用MySQL、Postgres、SQLite、Redis、MongoDB 或者 CouchDB。python
還有一些數據庫抽象層代碼包供選擇,例如 SQLAlchemy 和MongoEngine。你能夠使用這些抽象包直接處理高等級的 Python 對象,而不用處理如表、文檔或查詢語言此類的數據庫實體。mysql
咱們選擇使用的數據庫框架是 Flask-SQLAlchemy(http://pythonhosted.org/Flask-SQLAlchemy/),這個 Flask 擴展包裝了 SQLAlchemy(http://www.sqlalchemy.org/)框架。
Flask-SQLAlchemy 是一個 Flask 擴展,簡化了在 Flask 程序中使用 SQLAlchemy 的操做。
SQLAlchemy 是一個很強大的關係型數據庫框架,支持多種數據庫後臺。SQLAlchemy 提供了高層 ORM,也提供了使用數據庫原生 SQL 的低層功能。sql
(venv) $ pip install flask-sqlalchemy
在 Flask-SQLAlchemy 中,數據庫使用 URL 指定。最流行的數據庫引擎採用的數據庫 URL。shell
FLask-SQLAlchemy數據庫URL以下所示:數據庫
數據庫引擎 URL MySQL mysql://username:password@hostname/database Postgres postgresql://username:password@hostname/database SQLite(Unix) sqlite:////absolute/path/to/database SQLite(Windows) sqlite:///c:/absolute/path/to/database
在這些 URL 中,hostname 表示 MySQL 服務所在的主機,能夠是本地主機(localhost),
也能夠是遠程服務器。數據庫服務器上能夠託管多個數據庫,所以 database 表示要使用的
數據庫名。若是數據庫須要進行認證,username 和 password 表示數據庫用戶密令。flask
注意:SQLite 數據庫不須要使用服務器,所以不用指定 hostname、username 和password。URL 中的 database 是硬盤上文件的文件名。服務器
程序使用的數據庫 URL 必須保存到 Flask 配置對象的 SQLALCHEMY_DATABASE_URI 鍵中。配置對象中還有一個頗有用的選項,即 SQLALCHEMY_COMMIT_ON_TEARDOWN 鍵,將其設爲 True時,每次請求結束後都會自動提交數據庫中的變更。其餘配置選項的做用請參閱 Flask-SQLAlchemy 的文檔。session
test.pyapp
from flask_sqlalchemy import SQLAlchemy from flask import Flask import os basedir = os.path.abspath(os.path.dirname(__file__)) app = Flask(__name__) app.config['SQLALCHEMY_DATABASE_URI'] =\ 'sqlite:///' + os.path.join(basedir, 'data.sqlite') app.config['SQLALCHEMY_COMMIT_ON_TEARDOWN'] = True db = SQLAlchemy(app)
db 對象是 SQLAlchemy 類的實例,表示程序使用的數據庫,同時還得到了 Flask-SQLAlchemy提供的全部功能。框架
模型這個術語表示程序使用的持久化實體。在 ORM 中,模型通常是一個 Python 類,類中的屬性對應數據庫表中的列。
test.py:定義 Role 和 User 模型
class Role(db.Model): __tablename__ = 'roles' id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(64), unique=True) def __repr__(self): return '<Role %r>' % self.name class User(db.Model): __tablename__ = 'users' id = db.Column(db.Integer, primary_key=True) username = db.Column(db.String(64), unique=True, index=True) def __repr__(self): return '<User %r>' % self.username
類變量 __tablename__ 定義在數據庫中使用的表名。若是沒有定義 __tablename__ ,Flask-SQLAlchemy 會使用一個默認名字,但默認的表名沒有遵照使用複數形式進行命名的約定,因此最好由咱們本身來指定表名。
其他的類變量是該模型的屬性,被定義爲 db.Column類的實例。
注意:Flask-SQLAlchemy 要求每一個模型都要定義 主鍵 ,這一列常常命名爲 id 。
db.Column 類構造函數的第一個參數是數據庫列和模型屬性的類型。 最經常使用的SQLAlchemy列類型 類型名 Python類型 說 明 Integer int 普通整數,通常是 32 位 SmallInteger int 取值範圍小的整數,通常是 16 位 BigInteger int 或 long 不限制精度的整數 Float float 浮點數 Numeric decimal.Decimal 定點數 String str 變長字符串 Text str 變長字符串,對較長或不限長度的字符串作了優化 Unicode unicode 變長 Unicode 字符串 UnicodeText unicode 變長 Unicode 字符串,對較長或不限長度的字符串作了優化 Boolean bool 布爾值 Date datetime.date 日期 Time datetime.time 時間 DateTime datetime.datetime 日期和時間 Interval datetime.timedelta 時間間隔 Enum str 一組字符串 PickleType 任何 Python 對象 自動使用 Pickle 序列化 LargeBinary str 二進制文件 db.Column 中其他的參數指定屬性的配置選項。列出了一些可用選項。 最常使用的SQLAlchemy列選項 選項名 說 明 primary_key 若是設爲 True ,這列就是表的主鍵 unique 若是設爲 True ,這列不容許出現重複的值 index 若是設爲 True ,爲這列建立索引,提高查詢效率 nullable 若是設爲 True ,這列容許使用空值;若是設爲 False ,這列不容許使用空值 default 爲這列定義默認值
(venv) $ python test.py shell
>>> from hello import db
>>> db.create_all()
若是修改模型後要把改動應用到現有的數據庫中,這一特性會帶來不便,它把數據庫中原有的數據都銷燬了。更新現有數據庫表的粗暴方式是先刪除舊錶再從新建立:
>>> db.drop_all()
>>> db.create_all()
下面這段代碼建立了一些角色和用戶:
>>> from hello import Role, User
>>> admin_role = Role(name='Admin')
>>> mod_role = Role(name='Moderator')
>>> user_role = Role(name='User')
>>> user_john = User(username='john', role=admin_role)
>>> user_susan = User(username='susan', role=user_role)
>>> user_david = User(username='david', role=user_role)
經過數據庫會話管理對數據庫所作的改動,在 Flask-SQLAlchemy 中,會話由 db.session表示。準備把對象寫入數據庫以前,先要將其添加到會話中:
>>> db.session.add(admin_role)
>>> db.session.add(mod_role)
>>> db.session.add(user_role)
>>> db.session.add(user_john)
>>> db.session.add(user_susan)
>>> db.session.add(user_david)
或者簡寫成:
>>> db.session.add_all([admin_role, mod_role, user_role,
... user_john, user_susan, user_david])
爲了把對象寫入數據庫,咱們要調用 commit() 方法提交會話:
>>> db.session.commit()
注意:數據庫會話能保證數據庫的一致性。提交操做使用原子方式把會話中的對象所有寫入數據庫。若是在寫入會話的過程當中發生了錯誤,整個會話都會失效。若是你始終把相關改動放在會話中提交,就能避免因部分更新致使的數據庫不一致性。
數據庫會話也可 回滾 。調用 db.session.rollback() 後,添加到數據庫會話中的全部對象都會還原到它們在數據庫時的狀態。
在數據庫會話上調用 add() 方法也能更新模型。咱們繼續在以前的 shell 會話中進行操做,
下面這個例子把 "Admin" 角色重命名爲 "Administrator" :
>>> admin_role.name = 'Administrator'
>>> db.session.add(admin_role)
>>> db.session.commit()
數據庫會話還有個 delete() 方法。下面這個例子把 "Moderator" 角色從數據庫中刪除:
>>> db.session.delete(mod_role)
>>> db.session.commit()
注意,刪除與插入和更新同樣,提交數據庫會話後纔會執行。
1.Flask-SQLAlchemy 爲每一個模型類都提供了 query 對象。最基本的模型查詢是取回對應表中的全部記錄:
>>> Role.query.all()
[<Role u'Administrator'>, <Role u'User'>]
>>> User.query.all()
[<User u'john'>, <User u'susan'>, <User u'david'>]
2.使用過濾器能夠配置 query 對象進行更精確的數據庫查詢。下面這個例子查找角色爲"User" 的全部用戶:
>>> User.query.filter_by(role=user_role).all()
[<User u'susan'>, <User u'david'>]
3.若要查看 SQLAlchemy 爲查詢生成的原生 SQL 查詢語句,只需把 query 對象轉換成字符串:
>>> str(User.query.filter_by(role=user_role))
'SELECT users.id AS users_id, users.username AS users_username,
users.role_id AS users_role_id FROM users WHERE :param_1 = users.role_id'
4.若是你退出了 shell 會話,前面這些例子中建立的對象就不會以 Python 對象的形式存在,而
是做爲各自數據庫表中的行。若是你打開了一個新的 shell 會話,就要從數據庫中讀取行,
再從新建立 Python 對象。下面這個例子發起了一個查詢,加載名爲 "User" 的用戶角色:
>>> user_role = Role.query.filter_by(name='User').first()
5.filter_by() 等過濾器在 query 對象上調用,返回一個更精確的 query 對象。多個過濾器能夠一塊兒調用,直到得到所需結果。下表列出了可在 query 對象上調用的經常使用過濾器。完整的列表參見 SQLAlchemy 文檔
(http://docs.sqlalchemy.org)。
經常使用的SQLAlchemy查詢過濾器
過濾器 說 明
filter() 把過濾器添加到原查詢上,返回一個新查詢
filter_by() 把等值過濾器添加到原查詢上,返回一個新查詢
limit() 使用指定的值限制原查詢返回的結果數量,返回一個新查詢
offset() 偏移原查詢返回的結果,返回一個新查詢
order_by() 根據指定條件對原查詢結果進行排序,返回一個新查詢
group_by() 根據指定條件對原查詢結果進行分組,返回一個新查詢
6.在查詢上應用指定的過濾器後,經過調用 all() 執行查詢,以列表的形式返回結果。除了all() 以外,還有其餘方法能觸發查詢執行。下表 列出了執行查詢的其餘方法。
最常使用的SQLAlchemy查詢執行函數
方 法 說 明 all() 以列表形式返回查詢的全部結果 first() 返回查詢的第一個結果,若是沒有結果,則返回 None first_or_404() 返回查詢的第一個結果,若是沒有結果,則終止請求,返回 404 錯誤響應 get() 返回指定主鍵對應的行,若是沒有對應的行,則返回 None get_or_404() 返回指定主鍵對應的行,若是沒找到指定的主鍵,則終止請求,返回 404 錯誤響應 count() 返回查詢結果的數量 paginate() 返回一個 Paginate 對象,它包含指定範圍內的結果