如今咱們建立了模型,生成了數據庫和表,下面來學習經常使用的數據庫操做,數據庫操做主要是CRUD,即Create(建立)、Read(讀取/查詢)、Update(更新)和Delete(刪除)。python
SQLAlchemy使用數據庫會話來管理數據庫操做,這裏的數據庫會話也稱爲事務(transaction)。 Flask-SQLAlchemy自動幫咱們建立會話,能夠經過db.session屬性獲取。sql
數據庫中的會話表明一個臨時存儲區,你對數據庫作出的改動都會存放在這裏。你能夠調用add()方法將新建立的對象添加到數據庫會話中,或是對會話中的對象進行更新。只有當你對數據庫會話對象調用commit()方法時,改動纔會提交到數據庫,這確保了數據提交的一致性。另外,數據庫會話也支持回滾操做。當你對會話調用rollback()方法時,添加到會話中且未提交的改動都將被撤銷。shell
下面咱們在python shell中操做CRUD操做。默認狀況下,Flask-SQLALchemy(>=2.3.0版本)會自動爲模型類生成一個__repr__()方法。當在python shell中調用模型類的對象時,__repr__()方法會返回一條相似」<模型類名主鍵值>」的字符串,好比<Note 2>。下面示例中,模型類都從新定義了__repr__()方法,返回一些更有用的信息,好比:數據庫
class Note(db.Model): id = db.Column(db.Integer, primary_key=True) db.Column() body = db.Column(db.Text) def __repr__(self): # %r是用repr()方法處理對象,返回類型自己,而不進行類型轉化 return '<Note %r>' % self.body
在實際開發中,這並非必須的。session
添加一條新紀錄到數據庫分三步:app
1) 建立python對象(實例化模型類)做爲一條記錄函數
2) 添加新建立的記錄到數據庫會話。學習
3) 提交數據庫會話spa
下面的示例向數據庫中添加了三條留言:code
>>> from app import db, Note >>> note1=Note(body='remember Sam Xia') >>> note2 = Note(body='Rose') >>> note3 = Note(body = 'I AM HERE TO TRUW BUBLEGUM AND KIK ASS, AND NOW I AM ALL OUT OF BUBLEGUM~') >>> db.session.add(note1) >>> db.session.add(note2) >>> db.session.add(note3) >>> db.session.commit()
在這個例子中,首先從app模塊導入db對象和Note類,而後分別建立三個Note實例表示三條記錄,使用關鍵字參數傳入字段數據。咱們的Note類繼承自db.Model基類,db.Model基類會爲Note類提供一個構造函數,接收匹配類屬性名稱的參數值,並賦值給對應的類屬性,因此咱們不須要本身在Note類中定義構造方法。接着咱們調用add()方法把這三個Note對象添加到會話對象db.session中,最後調用commit()方法提交會話。
除了依次調用add()方法添加多個記錄,也可使用add_all()依次添加包含全部記錄對象的列表。
咱們在建立模型類實例的時候並無定義id字段的數據,這是由於主鍵由SQLAlchemy管理。模型類對象建立後做爲臨時對象(transient),當你提交數據庫會話後,模型類對象纔會轉換爲數據庫記錄寫入數據庫中,這時模型類對象會自動獲取id值:
>>> note2.id
3
Flask-SQLAlchemy提供了一個SQLALCHEMY_COMMIT_ON_TEARDOWN配置,將其設爲True能夠設置自動調用commit()方法提交數據庫會話。由於存在潛在的Bug,目前不建議使用。
可使用db.session.commit()方法的方式提交數據庫會話。
如何從數據庫取回數據呢,使用模型類提供的query屬性附加調用各類過濾方法及查詢方法能夠完成這個任務。
通常來講,一個完整的查詢遵循下面的模式:
<模型類>.query.<過濾方法>.<查詢方法>
從某個模型類觸發,經過在query屬性對應的Query對象上附加的過濾方法和查詢函數對模型類對應的表中的記錄進行各類篩選和調整,最終返回包含對應數據庫記錄數據的模型類實例,對返回的實例調用屬性便可獲取對應的字段數據。
SQLAlchemy提供了許多查詢方法用來獲取記錄,以下表:
表中的first_or_404()、get_or_404()以及paginate()方法是Flask-SQLAlchemy附加的查詢方法。
下面是對Note類進行查詢的幾個例子。all()返回全部記錄:
>>> Note.query.all() [<Note u'Hello~'>, <Note u'remember Sam Xia'>, <Note u'Rose'>, <Note u'I AM HERE TO TRUW BUBLEGUM AND KIK ASS, AND NOW I AM ALL OUT OF BUBLEGUM~'>]
>>> note1 = Note.query.first() >>> note1 <Note u'Hello~'>
>>> note2=Note.query.get(2) >>> note2 <Note u'remember Sam Xia'> >>> note2.body u'remember Sam Xia'
>>> Note.query.count()
4
SQLAlchemy還提供了許多過濾方法,使用這些過濾方法能夠獲取更精確的查詢,好比獲取指定字段值的記錄。對模型類的query屬性存儲的query對象調用過濾方法將返回一個更精確的query對象(簡稱爲查詢對象)。由於每一個過濾方法都會返回新的查詢對象,因此過濾器能夠疊加使用。在查詢對象上調用前面說的查詢方法,便可得到一個包含過濾後的記錄的列表。經常使用的查詢過濾方法以下所示:
filter()方法是最基礎的查詢方法。它使用指定的規則來過濾記錄,下面的示例在數據庫裏找出了body字段值爲」Rose」的記錄:
>>> Note.query.filter(Note.body=='Rose').first() <Note u'Rose'>
直接打印查詢對象或將其轉換爲字符串能夠查看對應當前SQL語句:
>>> print Note.query.filter_by(body='Rose') SELECT note.id AS note_id, note.body AS note_body FROM note WHERE note.body = ?
在filter()方法中傳入表達式時,除了」==」以及表示不等於的」!=」,其餘經常使用的查詢操做符以及使用示例以下所示:
>>> Note.query.filter(Note.body.like('%Sam%')).first() <Note u'remember Sam Xia'>
>>> Note.query.filter(Note.body.in_(['Rose','Sam'])).first() <Note u'Rose'>
>>> Note.query.filter(~Note.body.in_(['foo'])).all() [<Note u'Hello~'>, <Note u'remember Sam Xia'>, <Note u'Rose'>, <Note u'I AM HERE TO TRUW BUBLEGUM AND KIK ASS, AND NOW I AM ALL OUT OF BUBLEGUM~'>]
使用and_()
>>>from sqlalchemy import and_ >>> Note.query.filter(and_(Note.body == 'Rose', Note.id == 3)).all() [<Note u'Rose'>]
或者再filter()中加入多個表達式,使用逗號分隔
>>> Note.query.filter(Note.body == 'Rose', Note.id == 3).all() [<Note u'Rose'>]
或疊加調用多個filter()/filter_by()方法
filter()中的等號是兩個
>>> Note.query.filter(Note.body == 'Rose').filter(Note.id == 3).all() [<Note u'Rose'>]
注意filter_by()中的等號是一個
>>> Note.query.filter_by(body='Rose').filter_by(id=3).all() [<Note u'Rose'>]
>>> Note.query.filter(or_(Note.body == 'Rose', Note.id == 2)).all() [<Note u'remember Sam Xia'>, <Note u'Rose'>]
和filter()方法相比,filter_by()方法更易於使用。在filter_by()方法中,可使用關鍵字表達式來指定過濾規則。更方便的是,能夠在這個過濾器中直接使用字段名稱。下面的例使用filter_by()過濾器完成了一樣的任務:
>>> Note.query.filter_by(body = 'Rose').all() [<Note u'Rose'>]
更新一條記錄分揀單,直接賦值給模型類的字段屬性就能夠改變字段值,而後調用gcommit()方法提交會話便可,例如:
>>> note = Note.query.get(2) >>> note.body u'remember Sam Xia' >>> note.body = 'Life is a dream' >>> db.session.commit() >>> note.body u'Life is a dream'
只有要插入新的記錄或要將現有的記錄添加到會話中時才須要使用add()方法,單純要更新現有的記錄時只須要直接爲屬性賦新值,而後提交會話。
刪除記錄和添加記錄類似,不過要把add()方法換成delete()方法,最後都要調用commit()方法提交記錄。
例如刪除id(主鍵)爲2的記錄:
>>> note = Note.query.get(1) >>> db.session.delete(note) >>> db.session.commit()