ORM
(Object Relational Mapper) 對象關係映射。指將面對對象得方法映射到數據庫中的關係對象中。
Flask-SQLAlchemy是一個Flask擴展,可以支持多種數據庫後臺,咱們能夠不須要關心SQL的處理細節,操做數據庫,一個基本關係對應一個類,而一個實體對應類的實例對象,經過調用方法操做數據庫。Flask-SQLAlchemy
有很完善的文檔。python
Flask-SQLAlchemy
是經過URL指定數據庫的鏈接信息的。
初始化的兩種方法以下(以鏈接Mysql數據庫爲例):mysql
from flask_sqlalchemy import SQLAlchemy from flask import FLask app = Flask(__name__) app.config['SQLALCHEMY_DATABASE_URI'] = \ "mysql://root:12345@localhost/test" db = SQLAlchemy(app)
或者sql
from flask_sqlalchemy import SQLAlchemy from flask import FLask db = SQLAlchemy() def create_app(): app = Flask(__name__) db.init_app(app) return app
二者的區別在於:第一種不須要啓動flask的app_context
;可是第二種方法則須要,由於可能會建立多個Flask應用,可是個人理解是通常地開發時,Flask實例是延遲建立的,由於在運行時難以修改配置信息,這種方法符合這種狀況。Flask-SQLAlchemy
的則須要在Flask.config
中聲明。更多詳細信息須要查配置。例如配置信息中指出SQLAlchemy
是能夠綁定多個數據庫引擎。再例如:在新浪SAE雲平臺開發我的博客時遇到gone away
這種問題就須要添加SQLALCHEMY_POOL_RECYCLE
信息,新浪開發者文檔中有說明。數據庫
SQLAlchemy是如何處理對象到關係的?實例來自於數據庫系統概論內容。flask
建立學生students表segmentfault
class Student(db.Model): __tablename__ = 'students' #指定表名 sno = db.Column(db.String(10), primary_key=True) sname = db.Column(db.String(10)) sage = db.Column(db.Integer)
API文檔說明建立對象須要繼承db.Model類
關聯數據表項,db.Model類
繼承Query類
提供有數據查詢方法;__tablename__
指定數據庫的表名,在Flask-SQLAlchemy
中是可省的。Column
指定表字段。app
SQLAlchemy支持字段類型有:函數
類型名 | python類型 | 說明 |
---|---|---|
Integer | int | 普通整數,32位 |
Float | float | 浮點數 |
String | str | 變長字符串 |
Text | str | 變長字符串,對較長字符串作了優化 |
Boolean | bool | 布爾值 |
PickleType | 任何python對象 | 自動使用Pickle序列化 |
來源於Simple Example,Flask Web開發有更詳細的內容。
其他的參數指定屬性的配置選項,經常使用的配置選項以下:優化
選項名 | 說明 |
---|---|
primarykey | 若是設爲True,表示主鍵 |
unique | 若是設爲True,這列不重複 |
index | 若是設爲True,建立索引,提高查詢效率 |
nullable | 若是設爲True,容許空值 |
default | 爲這列定義默認值 |
如使用default
默認time屬性以下:代理
time = db.Column(db.Date, default=datetime.utcnow)
說明default
能夠接受lambda
表達式。
按建立單張表的方法,建立學院Deptment表
class Deptment(db.Model): __tablename__ = 'deptments' dno = db.Column(db.Integer, primary_key=True) dname = Sname = db.Column(db.String(10),index=True)
學院和學生是一對多的關係。Flask-SQLAlchemy
是經過db.relationship()
解決一對多的關係。在Dept中添加屬性,代碼以下:
class Deptment(db.Model): ... students = db.relationship('Student', backref='dept') class Student(db.Model): ... dept_no = db.Column(db.Integer, db.ForeignKey('deptments.dno'))
表的外鍵由db.ForeignKey
指定,傳入的參數是表的字段。db.relations
它聲明的屬性不做爲表字段,第一個參數是關聯類的名字,backref
是一個反向身份的代理,至關於在Student類中添加了dept的屬性。例如,有Deptment實例dept和Student實例stu。dept.students.count()
將會返回學院學生人數;stu.dept.first()
將會返回學生的學院信息的Deptment類實例。通常來說db.relationship()
會放在一
這一邊。
多對多的關係能夠分解成一對多關係,例如:學生選課,學生與課程之間的關係:
sc = db.Table('sc', db.Column('sno', db.String(10), db.ForeignKey('students.sno')) db.Column('cno',db.String(10), db.ForeignKey('courses.cno')) ) Class Course(db.Model): __tablename__ = 'courses' cno = db.Column(db.String(10), primary_key=True) cname = db.Column(db.String(10), index=True) students = db.relationship('Student', secondary=sc, backref=db.backref('course',lazy='dynamic'), lazy='dynamic' )
sc
表由db.Table
聲明,咱們不須要關心這張表,由於這張表將會由SQLAlchemy
接管,它惟一的做用是做爲students表和courses表關聯表,因此必須在db.relationship()
中指出sencondary
關聯表參數。lazy
是指查詢時的惰性求值的方式,這裏有詳細的參數說明,而db.backref
是聲明反向身份代理,其中的lazy
參數是指明反向查詢的惰性求值方式,SQLAlchemy
鼓勵這種方式聲明多對多的關係。
可是若是關聯表中有自定義的字段,如sc表中添加成績字段則須要更改表聲明方式,將sc
更改成繼承db.Model
的對象並設置sc:courses = 1:n
和sc:student = 1:n
的關係。
Flask-SQLAlchemy查詢中有詳細的說明。建立關係後該如何查詢到對象?
SQLAlchemy有查詢過濾器以下:
過濾器 | 說明 |
---|---|
filter() | 把過濾器添加到原查詢,返回新查詢 |
filter_by() | 把等值過濾器添加到原查詢,返回新查詢 |
limit() | 使用指定值限制原查詢返回的結果數量,返回新查詢 |
offset() | 偏移原查詢返回的結果,返回新查詢 |
order_by() | 排序返回結果,返回新查詢 |
groupby() | 原查詢分組,返回新查詢 |
這些過濾器返回的結果都是一個新查詢,個人理解是這些查詢實際上是生成的SQL語句,lazy
的惰性求值方式也體如今查詢上,而這些語句不能生成須要查詢的對象,須要調用其餘的方法生成對象。
SQL查詢執行函數:
方法 | 說明 |
---|---|
all() | 以列表形式返回結果 |
first() | 返回第一個結果,若是沒有返回None |
first_or_404() | 返回第一個結果,若是沒有拋出404異常 |
get() | 返回主鍵對應記錄,沒有則返回None |
get_or_404() | 返回主鍵對應記錄,若是沒有拋出404異常 |
count() | 返回查詢結果數量 |
paginate() | 返回paginate對象,此對象用於分頁 |