Flask-SQLAlchemy 學習總結

初始化和配置

ORM(Object Relational Mapper) 對象關係映射。指將面對對象得方法映射到數據庫中的關係對象中。
Flask-SQLAlchemy是一個Flask擴展,能夠支持多種數據庫後臺,我們可以不需要關心SQL的處理細節,操作數據庫,一個基本關係對應一個類,而一個實體對應類的實例對象,通過調用方法操作數據庫。Flask-SQLAlchemy有很完善的文檔。

Flask-SQLAlchemy是通過URL指定數據庫的連接信息的。
初始化的兩種方法如下(以連接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)

或者

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處理 對象->關係

SQLAlchemy是如何處理對象到關係的?實例來自於數據庫系統概論內容。

簡單實例

創建學生students表

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指定表字段。

SQLAlchemy支持字段類型有:

類型名python類型說明
Integerint普通整數,32位
Floatfloat浮點數
Stringstr變長字符串
Textstr變長字符串,對較長字符串做了優化
Booleanbool布爾值
PickleType任何python對象自動使用Pickle序列化

來源於Simple ExampleFlask 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的關係。


SQLALchemy處理 關係->對象

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對象,此對象用於分頁
發佈了16 篇原創文章 · 獲贊 13 · 訪問量 8萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章