本文主要介紹如何使用flask操作數(shù)據(jù)庫(kù)。
數(shù)據(jù)庫(kù)按照一定規(guī)則保存程序數(shù)據(jù),程序再發(fā)起查詢?nèi)』厮璧臄?shù)據(jù)。Web程序最常用基于關(guān)系模型的數(shù)據(jù)庫(kù),這種數(shù)據(jù)庫(kù)也稱為SQL數(shù)據(jù),因?yàn)樗鼈兪褂媒Y(jié)構(gòu)化查詢語(yǔ)句。不過最近幾年文檔數(shù)據(jù)庫(kù)和鍵值對(duì)數(shù)據(jù)庫(kù)成了流行的替代選擇,這兩種數(shù)據(jù)庫(kù)合稱為NoSQL數(shù)據(jù)庫(kù)。
大多數(shù)的數(shù)據(jù)庫(kù)引擎都有對(duì)應(yīng)的Python包,包括開源寶和商業(yè)包。Flask并不限制你使用何種類型的數(shù)據(jù)庫(kù)包,因此可以根據(jù)自己的喜好選擇使用MySQL、Postgres、SQLite,Redis、MongoDB或者CouchDB。
如果這些都無法滿足需求,還有一些數(shù)據(jù)庫(kù)抽象層代碼包供選擇,例如SQLAlchemy和MongoEngine。你可以使用這些抽象包直接處理高等級(jí)的Python對(duì)象,而不用處理如表、文檔或查詢語(yǔ)言此類的數(shù)據(jù)庫(kù)實(shí)體。
選擇框架時(shí),你不一定非得選擇已經(jīng)集成了Flask的框架,但選擇這些框架可以節(jié)約你編寫集成代碼的時(shí)間。使用集成了Flask的框架可以簡(jiǎn)化配置和操作,所以專門為Flask開發(fā)的擴(kuò)展是你的首選。
關(guān)于選擇使用的數(shù)據(jù)庫(kù)框架,選擇的是Flask-SQLAlchemy。
0.安裝Flask-SQLAlchemy
pip install flask-sqlalchemy
1.配置Flask-SQLAlchemy
在Flask-SQLAlchemy中,數(shù)據(jù)庫(kù)使用URL指定。
MySQL : mysql://username:password@hostname/database
Postgres : postgresql://username:password@hostname/database
SQLite : sqlite:////absolute/path/to/database
在這些URL中,hostname表示MySQL服務(wù)所在的主機(jī),可以是本地主機(jī)(localhost),也可以是遠(yuǎn)程服務(wù)器。數(shù)據(jù)庫(kù)服務(wù)器上可以托管多個(gè)數(shù)據(jù)庫(kù),因此database表示要使用的數(shù)據(jù)庫(kù)名。如果數(shù)據(jù)庫(kù)需要進(jìn)行認(rèn)證,username和password表示數(shù)據(jù)庫(kù)的用戶名和密碼。
SQLite數(shù)據(jù)庫(kù)不需要使用服務(wù)器,因此不用指定hostname、username和password。URL中的database是硬盤上文件的文件名。
程序使用的數(shù)據(jù)庫(kù)URL必須保存到Flask配置對(duì)象的SQLALCHEMY_DATABASE_URI鍵中。配置對(duì)象中還有一個(gè)很有用的選項(xiàng),即SQLALCHEMY_ON_REARDOWN鍵,將其設(shè)置為True時(shí),每次請(qǐng)求結(jié)束后都會(huì)自動(dòng)提交數(shù)據(jù)庫(kù)中的變動(dòng)。
我們使用SQLite數(shù)據(jù)庫(kù),配置代碼 如下:
from flask import Flask
from flask.ext.sqlalchemy import SQLAlchemy
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)
2.定義模型
定義一個(gè)用戶表users和一個(gè)角色表roles,代碼如下:
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
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
解釋下:
0.兩個(gè)類User和Role繼承自db.Model
1.__tablename__用來指定表名稱
2.db.Column函數(shù)指定了數(shù)據(jù)庫(kù)中字段的類型,是否是主鍵(primary_key),是否唯一(unique),是否加索引(index),還有其他的比如:是否可以為空(nullable=True),默認(rèn)值(default)
3.關(guān)系
使用關(guān)系型數(shù)據(jù)庫(kù),不指定關(guān)系怎么能行。定義模型中我們沒有指定關(guān)系,一個(gè)用戶有一個(gè)角色,一個(gè)角色可以屬于多個(gè)用戶,典型的一對(duì)多的關(guān)系,如何在Flask-SQLAlchemy中定義關(guān)系?
上代碼:
class User(db.Model):
__tablename__ = 'users'
id = db.Column(db.Integer,primary_key=True)
username = db.Column(db.String(64),unique=True,index=True)
role_id = db.Column(db.Integer,db.ForeignKey('roles.id'))
def __repr__(self):
return '<User %r>' % self.username
class Role(db.Model):
__tablename__ = 'roles'
id = db.Column(db.Integer,primary_key=True)
name = db.Column(db.String(64),unique=True)
users = db.relationship('User',backref='role')
def __repr__(self):
return '<Role %r>' % self.name
添加了兩行代碼:
第一行,User類中:
role_id = db.Column(db.Integer,db.ForeignKey('roles.id'))
這句話比較好理解,和上面普通變量差不多,就是User類中添加了一個(gè)role_id變量,數(shù)據(jù)類型db.Integer,第二個(gè)參數(shù)指定外鍵是哪個(gè)表中哪個(gè)id。
第二行,Role類中:
users = db.Relationship('User',backref='role')
這句話比較復(fù)雜,仔細(xì)讀下面的話:
0.添加到Role模型中的users屬性代表這個(gè)關(guān)系的面向?qū)ο笠暯?。?duì)于一個(gè)Role類的實(shí)例,其users屬性將返回與角色相關(guān)聯(lián)的用戶組成的列表。
1.db.Relationship()第一個(gè)參數(shù)表明這個(gè)關(guān)系的另一端是哪個(gè)模型(類)。如果模型類尚未定義,可使用字符串形式指定。
2.db.Relationship()第二個(gè)參數(shù)backref,將向User類中添加一個(gè)role屬性,從而定義反向關(guān)系。這一屬性可替代role_id訪問Role模型,此時(shí)獲取的是模型對(duì)象,而不是外鍵的值。
上面的關(guān)系為一對(duì)多關(guān)系的表示,一對(duì)一怎么辦?
調(diào)用db.Relationship()時(shí)需要把userlist參數(shù)設(shè)置為False。如下:
db.Relationship('User',backref='role',uselist=False)
至于多對(duì)多關(guān)系,以后會(huì)慢慢介紹。
4.數(shù)據(jù)庫(kù)操作
數(shù)據(jù)庫(kù)操作,基本的一些:數(shù)據(jù)庫(kù)、表創(chuàng)建或刪除,數(shù)據(jù)的增刪改查。
0.創(chuàng)建數(shù)據(jù)庫(kù)和表
db.create_all()
上面說的users表和roles表就創(chuàng)建了。
1.刪除數(shù)據(jù)庫(kù)
db.drop_all()
1.插入行
role_admin = Role(name='Admin')
user_tom = User(username='tom',role=role_admin)
user_jim = User(username='jim',role=role_admin)
user_tim = User(username='tim',role=role_admin)
user_sam = User(username='sam',role=role_admin)
db.session.add(role_admin)
db.session.add(user_tom)
db.session.add(user_jim)
db.session.commit()
通過數(shù)據(jù)庫(kù)會(huì)話管理對(duì)數(shù)據(jù)庫(kù)所做的改動(dòng),在Flask-SQLAlchemy中,會(huì)話由db.session表示,準(zhǔn)備把隊(duì)形寫入數(shù)據(jù)庫(kù)之前,先要將其添加到會(huì)話中。寫入數(shù)據(jù)庫(kù)需要調(diào)用db.session.commit()方法。
2.修改行
我們將role_admin變量中name為Admin改成Administrator。
role_admin.name='Administrator'
db.session.add(role_admin)
db.session.commit()
3.刪除行
刪除Jim用戶
db.session.delete(user_jim)
db.session.commit()
4.查詢行
查詢所有用戶
User.query.all() #返回結(jié)果:[<User 'tom'>, <User 'tim'>, <User 'sam'>]
更多相關(guān)方面文檔請(qǐng)參考:SQLAlchemy文檔