Flask-SQLAlchemy 介紹

ORM

  • ORM 全拼Object-Relation Mapping.
  • 中文意爲 對象-關係映射.
  • 主要實現模型對象到關係數據庫數據的映射.html

優勢 :

  • 只須要面向對象編程, 不須要面向數據庫編寫代碼.
    • 對數據庫的操做都轉化成對類屬性和方法的操做.
    • 不用編寫各類數據庫的sql語句.
  • 實現了數據模型與數據庫的解耦, 屏蔽了不一樣數據庫操做上的差別.
    • 不在關注用的是mysqloracle...等.
    • 經過簡單的配置就能夠輕鬆更換數據庫, 而不須要修改代碼.

缺點 :

  • 相比較直接使用SQL語句操做數據庫,有性能損失.
  • 根據對象的操做轉換成SQL語句,根據查詢的結果轉化成對象, 在映射過程當中有性能損失.

Flask-SQLAlchemy安裝及設置

  • SQLALchemy 其實是對數據庫的抽象,讓開發者不用直接和 SQL 語句打交道,而是經過 Python 對象來操做數據庫,在捨棄一些性能開銷的同時,換來的是開發效率的較大提高
  • SQLAlchemy是一個關係型數據庫框架,它提供了高層的 ORM 和底層的原生數據庫的操做。flask-sqlalchemy 是一個簡化了 SQLAlchemy 操做的flask擴展。
  • 文檔地址:http://docs.jinkan.org/docs/flask-sqlalchemy

安裝

  • 安裝 flask-sqlalchemy
pip install flask-sqlalchemy
  • 若是鏈接的是 mysql 數據庫,須要安裝 mysqldb
pip install flask-mysqldb

數據庫鏈接設置

  • 在 Flask-SQLAlchemy 中,數據庫使用URL指定,並且程序使用的數據庫必須保存到Flask配置對象的 SQLALCHEMY_DATABASE_URI 鍵中
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://root:mysql@127.0.0.1:3306/test' 
  • 其餘設置:
# 動態追蹤修改設置,如未設置只會提示警告 app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True #查詢時會顯示原始SQL語句 app.config['SQLALCHEMY_ECHO'] = True 
  • 配置完成須要去 MySQL 中建立項目所使用的數據庫
$ mysql -uroot -pmysql
$ create database test charset utf8; 
  • 其餘配置
名字 備註
SQLALCHEMY_DATABASE_URI 用於鏈接的數據庫 URI 。例如:sqlite:////tmp/test.dbmysql://username:password@server/db
SQLALCHEMY_BINDS 一個映射 binds 到鏈接 URI 的字典。更多 binds 的信息見用 Binds 操做多個數據庫
SQLALCHEMY_ECHO 若是設置爲Ture, SQLAlchemy 會記錄全部 發給 stderr 的語句,這對調試有用。(打印sql語句)
SQLALCHEMY_RECORD_QUERIES 能夠用於顯式地禁用或啓用查詢記錄。查詢記錄 在調試或測試模式自動啓用。更多信息見get_debug_queries()。
SQLALCHEMY_NATIVE_UNICODE 能夠用於顯式禁用原生 unicode 支持。當使用 不合適的指定無編碼的數據庫默認值時,這對於 一些數據庫適配器是必須的(好比 Ubuntu 上 某些版本的 PostgreSQL )。
SQLALCHEMY_POOL_SIZE 數據庫鏈接池的大小。默認是引擎默認值(一般 是 5 )
SQLALCHEMY_POOL_TIMEOUT 設定鏈接池的鏈接超時時間。默認是 10 。
SQLALCHEMY_POOL_RECYCLE 多少秒後自動回收鏈接。這對 MySQL 是必要的, 它默認移除閒置多於 8 小時的鏈接。注意若是 使用了 MySQL , Flask-SQLALchemy 自動設定 這個值爲 2 小時。

鏈接其餘數據庫

完整鏈接 URI 列表請跳轉到 SQLAlchemy 下面的文檔 (Supported Databases) 。這裏給出一些 常見的鏈接字符串。python

  • Postgres:
postgresql://scott:tiger@localhost/mydatabase
  • MySQL:
mysql://scott:tiger@localhost/mydatabase
  • Oracle:
- oracle://scott:tiger@127.0.0.1:1521/sidname
  • SQLite (注意開頭的四個斜線):
sqlite:////absolute/path/to/foo.db

經常使用的SQLAlchemy字段類型

類型名 python中類型 說明
Integer int 普通整數,通常是32位
SmallInteger int 取值範圍小的整數,通常是16位
BigInteger int或long 不限制精度的整數
Float float 浮點數
Numeric decimal.Decimal 普通整數,通常是32位
String str 變長字符串
Text str 變長字符串,對較長或不限長度的字符串作了優化
Unicode unicode 變長Unicode字符串
UnicodeText unicode 變長Unicode字符串,對較長或不限長度的字符串作了優化
Boolean bool 布爾值
Date datetime.date 時間
Time datetime.datetime 日期和時間
LargeBinary str 二進制文件

經常使用的SQLAlchemy列選項

選項名 說明
primary_key 若是爲True,表明表的主鍵
unique 若是爲True,表明這列不容許出現重複的值
index 若是爲True,爲這列建立索引,提升查詢效率
nullable 若是爲True,容許有空值,若是爲False,不容許有空值
default 爲這列定義默認值

經常使用的SQLAlchemy關係選項

選項名 說明
backref 在關係的另外一模型中添加反向引用
primary join 明確指定兩個模型之間使用的聯結條件
uselist 若是爲False,不使用列表,而使用標量值
order_by 指定關係中記錄的排序方式
secondary 指定多對多中記錄的排序方式
secondary join 在SQLAlchemy中沒法自行決定時,指定多對多關係中的二級聯結條件

 

數據庫基本操做

  • 在Flask-SQLAlchemy中,插入、修改、刪除操做,均由數據庫會話管理。mysql

    • 會話用 db.session 表示。在準備把數據寫入數據庫前,要先將數據添加到會話中而後調用 commit() 方法提交會話。
  • 在 Flask-SQLAlchemy 中,查詢操做是經過 query 對象操做數據。sql

    • 最基本的查詢是返回表中全部數據,能夠經過過濾器進行更精確的數據庫查詢。

在視圖函數中定義模型類

from flask import Flask from flask_sqlalchemy import SQLAlchemy app = Flask(__name__) #設置鏈接數據庫的URL app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://root:mysql@127.0.0.1:3306/test' app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True #查詢時會顯示原始SQL語句 app.config['SQLALCHEMY_ECHO'] = True db = SQLAlchemy(app) class Role(db.Model): # 定義表名 __tablename__ = 'roles' # 定義列對象 id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(64), unique=True) us = db.relationship('User', backref='role') #repr()方法顯示一個可讀字符串 def __repr__(self): return 'Role:%s'% self.name class User(db.Model): __tablename__ = 'users' id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(64), unique=True, index=True) email = db.Column(db.String(64),unique=True) password = db.Column(db.String(64)) role_id = db.Column(db.Integer, db.ForeignKey('roles.id')) def __repr__(self): return 'User:%s'%self.name if __name__ == '__main__': app.run(debug=True) 

模型以前的關聯

一對多

class Role(db.Model): ... #關鍵代碼 us = db.relationship('User', backref='role', lazy='dynamic') ... class User(db.Model): ... role_id = db.Column(db.Integer, db.ForeignKey('roles.id')) 
  • 其中realtionship描述了Role和User的關係。在此文中,第一個參數爲對應參照的類"User"
  • 第二個參數backref爲類User申明新屬性的方法
  • 第三個參數lazy決定了何時SQLALchemy從數據庫中加載數據
    • 若是設置爲子查詢方式(subquery),則會在加載完Role對象後,就當即加載與其關聯的對象,這樣會讓總查詢數量減小,但若是返回的條目數量不少,就會比較慢
      • 設置爲 subquery 的話,role.users 返回全部數據列表
    • 另外,也能夠設置爲動態方式(dynamic),這樣關聯對象會在被使用的時候再進行加載,而且在返回前進行過濾,若是返回的對象數不少,或者將來會變得不少,那最好採用這種方式
      • 設置爲 dynamic 的話,role.users 返回查詢對象,並無作真正的查詢,能夠利用查詢對象作其餘邏輯,好比:先排序再返回結果

多對多

registrations = db.Table('registrations', db.Column('student_id', db.Integer, db.ForeignKey('students.id')), db.Column('course_id', db.Integer, db.ForeignKey('courses.id')) ) class Course(db.Model): ... class Student(db.Model): ... classes = db.relationship('Course',secondary=registrations, backref='student', lazy='dynamic') 

經常使用的SQLAlchemy查詢過濾器

過濾器 說明
filter() 把過濾器添加到原查詢上,返回一個新查詢
filter_by() 把等值過濾器添加到原查詢上,返回一個新查詢
limit 使用指定的值限定原查詢返回的結果
offset() 偏移原查詢返回的結果,返回一個新查詢
order_by() 根據指定條件對原查詢結果進行排序,返回一個新查詢
group_by() 根據指定條件對原查詢結果進行分組,返回一個新查詢

經常使用的SQLAlchemy查詢執行器

方法 說明
all() 以列表形式返回查詢的全部結果
first() 返回查詢的第一個結果,若是未查到,返回None
first_or_404() 返回查詢的第一個結果,若是未查到,返回404
get() 返回指定主鍵對應的行,如不存在,返回None
get_or_404() 返回指定主鍵對應的行,如不存在,返回404
count() 返回查詢結果的數量
paginate() 返回一個Paginate對象,它包含指定範圍內的結果

建立表:

db.create_all()

刪除表

db.drop_all()

插入一條數據

ro1 = Role(name='admin')
db.session.add(ro1)
db.session.commit()
#再次插入一條數據
ro2 = Role(name='user')
db.session.add(ro2)
db.session.commit()

一次插入多條數據

us1 = User(name='wang',email='wang@163.com',password='123456',role_id=ro1.id) us2 = User(name='zhang',email='zhang@189.com',password='201512',role_id=ro2.id) us3 = User(name='chen',email='chen@126.com',password='987654',role_id=ro2.id) us4 = User(name='zhou',email='zhou@163.com',password='456789',role_id=ro1.id) us5 = User(name='tang',email='tang@itheima.com',password='158104',role_id=ro2.id) us6 = User(name='wu',email='wu@gmail.com',password='5623514',role_id=ro2.id) us7 = User(name='qian',email='qian@gmail.com',password='1543567',role_id=ro1.id) us8 = User(name='liu',email='liu@itheima.com',password='867322',role_id=ro1.id) us9 = User(name='li',email='li@163.com',password='4526342',role_id=ro2.id) us10 = User(name='sun',email='sun@163.com',password='235523',role_id=ro2.id) db.session.add_all([us1,us2,us3,us4,us5,us6,us7,us8,us9,us10]) db.session.commit() """ 查詢全部用戶數據 查詢有多少個用戶 查詢第1個用戶 查詢id爲4的用戶[3種方式] 查詢名字結尾字符爲g的全部數據[開始/包含] 查詢名字不等於wang的全部數據[2種方式] 查詢名字和郵箱都以 li 開頭的全部數據[2種方式] 查詢password是 `123456` 或者 `email` 以 `itheima.com` 結尾的全部數據 查詢id爲 [1, 3, 5, 7, 9] 的用戶列表 查詢name爲liu的角色數據 查詢全部用戶數據,並以郵箱排序 每頁3個,查詢第2頁的數據 """ 

查詢:filter_by精確查詢

返回名字等於wang的全部人數據庫



User.query.filter_by(name='wang').all()

first()返回查詢到的第一個對象

User.query.first()

all()返回查詢到的全部對象



User.query.all()

ilter模糊查詢,返回名字結尾字符爲g的全部數據。



User.query.filter(User.name.endswith('g')).all()

get():參數爲主鍵,若是主鍵不存在沒有返回內容

User.query.get()

邏輯非,返回名字不等於wang的全部數據



User.query.filter(User.name!='wang').all()

not_ 至關於取反



from sqlalchemy import not_ User.query.filter(not_(User.name=='chen')).all()

邏輯與,須要導入and,返回and()條件知足的全部數據



from sqlalchemy import and_ User.query.filter(and_(User.name!='wang',User.email.endswith('163.com'))).all()

邏輯或,須要導入or_



from sqlalchemy import or_ User.query.filter(or_(User.name!='wang',User.email.endswith('163.com'))).all()

查詢數據後刪除

user = User.query.first()
db.session.delete(user)
db.session.commit()
User.query.all()

更新數據



user = User.query.first() user.name = 'dong' db.session.commit() User.query.first()

關聯查詢示例:

角色和用戶的關係是一對多的關係,一個角色能夠有多個用戶,一個用戶只能屬於一個角色。編程

  • 查詢角色的全部用戶


#查詢roles表id爲1的角色 ro1 = Role.query.get(1) #查詢該角色的全部用戶 ro1.us.all()
  • 查詢用戶所屬角色


#查詢users表id爲3的用戶 us1 = User.query.get(3) #查詢用戶屬於什麼角色 us1.role
圖書管理系統

定義模型
模型表示程序使用的數據實體,在Flask-SQLAlchemy中,模型通常是Python類,繼承自db.Model,db是SQLAlchemy類的實例,表明程序使用的數據庫。

類中的屬性對應數據庫表中的列。id爲主鍵,是由Flask-SQLAlchemy管理。db.Column類構造函數的第一個參數是數據庫列和模型屬性類型。

注:若是沒有在建立數據庫的時候指定編碼的話,向數據庫中插入中文後,會報錯,那麼須要修改數據庫的編碼集:

alter database 數據庫名 CHARACTER SET utf8
以下示例:定義了兩個模型類,做者和書名。

#coding=utf-8
from flask import Flask,render_template,redirect,url_for
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)

#設置鏈接數據
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://root:mysql@127.0.0.1:3306/test2'

app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True

#實例化SQLAlchemy對象
db = SQLAlchemy(app)

#定義模型類-做者
class Author(db.Model):
    __tablename__ = 'author'
    id = db.Column(db.Integer,primary_key=True)
    name = db.Column(db.String(32),unique=True
    au_book = db.relationship('Book',backref='author')
    def __repr__(self):
        return 'Author:%s' %self.name

#定義模型類-書名
class Book(db.Model):
    __tablename__ = 'books'
    id = db.Column(db.Integer,primary_key=True)
    name = db.Column(db.String(32))
    au_book = db.Column(db.Integer,db.ForeignKey('author.id'))
    def __str__(self):
        return 'Book:%s,%s'%(self.info,self.lead)

建立表



if __name__ == '__main__': db.drop_all() db.create_all() app.run(debug=True)

添加測試數據



#生成數據 au1 = Author(name='老王') au2 = Author(name='老尹') au3 = Author(name='老劉') # 把數據提交給用戶會話 db.session.add_all([au1, au2, au3]) # 提交會話 db.session.commit() bk1 = Book(name='老王回憶錄', author_id=au1.id) bk2 = Book(name='我讀書少,你別騙我', author_id=au1.id) bk3 = Book(name='如何才能讓本身更騷', author_id=au2.id) bk4 = Book(name='怎樣征服美麗少女', author_id=au3.id) bk5 = Book(name='如何征服英俊少男', author_id=au3.id) # 把數據提交給用戶會話 db.session.add_all([bk1, bk2, bk3, bk4, bk5]) # 提交會話 db.session.commit()

數據顯示&表單添加

數據顯示

  • 定義路由函數,並將 Author 和 Book 的全部結果傳到模板
@app.route('/',methods=['GET','POST']) def index(): author = Author.query.all() book = Book.query.all() return render_template('index.html',author=author,book=book) 
  • 模版關鍵代碼


<ul> {% for x in author %} <li>{{ x }}</li> {% endfor %} </ul> <hr> <ul> {% for x in book %} <li>{{ x }}</li> {% endfor %} </ul>

表單添加

  • 定義表單類
from flask_wtf import FlaskForm from wtforms.validators import DataRequired from wtforms import StringField,SubmitField #建立表單類,用來添加信息 class Append(FlaskForm): au_info = StringField(validators=[DataRequired()]) bk_info = StringField(validators=[DataRequired()]) submit = SubmitField(u'添加') 
  • 傳入至模版中
#建立表單對象 @app.route('/',methods=['GET','POST']) def index(): author = Author.query.all() book = Book.query.all() form = Append() return render_template('index.html',author=author,book=book,form=form) 
  • 模板中代碼


<form method="post"> {{ form.csrf_token }} <p>做者:{{ form.au_info }}</p> <p>書名:{{ form.bk_info }}</p> <p>{{ form.submit }}</p> </form>

表單驗證

@app.route('/', methods=['get', 'post']) def index(): append_form = Append() if request.method == 'POST': if append_form.validate_on_submit(): author_name = append_form.au_info.data book_name = append_form.bk_info.data # 判斷數據是否存在 author = Author.query.filter_by(name=author_name).first() if not author: try: # 先添加做者 author = Author(name=author_name) db.session.add(author) db.session.commit() # 再添加書籍 book = Book(name=book_name, author_id=author.id) db.session.add(book) db.session.commit() except Exception as e: db.session.rollback() print e flash("數據添加錯誤") else: book_names = [book.name for book in author.books] if book_name in book_names: flash('該做者已存在相同的書名') else: try: book = Book(name=book_name, author_id=author.id) db.session.add(book) db.session.commit() except Exception as e: db.session.rollback() print e flash('數據添加錯誤') else: flash('數據輸入有問題') authors = Author.query.all() books = Book.query.all() return render_template('test2.html', authors=authors, books=books, append_form=append_form) 
  • 從新編寫html文件展現列表書籍
<h2>書籍列表</h2>
<ul>
{% for author in authors %}
    <li>
        {{ author.name }}
        <ul>
            {% for book in author.books %}
                <li>{{ book.name }}
            {% else %}
                    <li>無書籍</li>
            {% endfor %}
        </ul>

    </li>
{% endfor %}
</ul>
  • 在form標籤下添加 flash 消息的顯示


{% for message in get_flashed_messages() %} {{ message }} {% endfor %}

刪除數據

  • 定義刪除author和book的路由
# 刪除做者 @app.route('/delete_author/<int:author_id>') def delete_author(author_id): author = Author.query.get(author_id) if not author: flash('數據不存在') else: try: Book.query.filter_by(author_id=author_id).delete() db.session.delete(author) db.session.commit() except Exception as e: db.session.rollback() print e flash('操做數據庫失敗') return redirect(url_for('index')) # 刪除書籍 @app.route('/delete_book/<int:book_id>') def delete_book(book_id): book = Book.query.get(book_id) if not book: flash('數據不存在') else: try: db.session.delete(book) db.session.commit() except Exception as e: db.session.rollback() print e flash('操做數據庫失敗') return redirect(url_for('index')) 
  • 在模版中添加刪除的 a 標籤連接


<h2>書籍列表</h2> <ul> {% for author in authors %} <li> {{ author.name }} <a href="/delete_author/{{ author.id }}">刪除</a> <ul> {% for book in author.books %} <li>{{ book.name }} <a href="/delete_book/{{ book.id }}">刪除</a></li> {% else %} <li>無書籍</li> {% endfor %} </ul> </li> {% endfor %} </ul>

數據庫遷移

  • 在開發過程當中,須要修改數據庫模型,並且還要在修改以後更新數據庫。最直接的方式就是刪除舊錶,但這樣會丟失數據。
  • 更好的解決辦法是使用數據庫遷移框架,它能夠追蹤數據庫模式的變化,而後把變更應用到數據庫中。
  • 在Flask中可使用Flask-Migrate擴展,來實現數據遷移。而且集成到Flask-Script中,全部操做經過命令就能完成。
  • 爲了導出數據庫遷移命令,Flask-Migrate提供了一個MigrateCommand類,能夠附加到flask-script的manager對象上。

首先要在虛擬環境中安裝Flask-Migrate。flask

pip install flask-migrate
  • 代碼文件內容:
#coding=utf-8 from flask import Flask from flask_sqlalchemy import SQLAlchemy from flask_migrate import Migrate,MigrateCommand from flask_script import Shell,Manager app = Flask(__name__) manager = Manager(app) app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://root:mysql@127.0.0.1:3306/Flask_test' app.config['SQLALCHEMY_COMMIT_ON_TEARDOWN'] = True app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True db = SQLAlchemy(app) #第一個參數是Flask的實例,第二個參數是Sqlalchemy數據庫實例 migrate = Migrate(app,db) #manager是Flask-Script的實例,這條語句在flask-Script中添加一個db命令 manager.add_command('db',MigrateCommand) #定義模型Role class Role(db.Model): # 定義表名 __tablename__ = 'roles' # 定義列對象 id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(64), unique=True) user = db.relationship('User', backref='role') #repr()方法顯示一個可讀字符串, def __repr__(self): return 'Role:'.format(self.name) #定義用戶 class User(db.Model): __talbe__ = '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:'.format(self.username) if __name__ == '__main__': manager.run() 

建立遷移倉庫



#這個命令會建立migrations文件夾,全部遷移文件都放在裏面。 python database.py db init

建立遷移腳本

  • 自動建立遷移腳本有兩個函數
    • upgrade():函數把遷移中的改動應用到數據庫中。
    • downgrade():函數則將改動刪除。
  • 自動建立的遷移腳本會根據模型定義和數據庫當前狀態的差別,生成upgrade()和downgrade()函數的內容。
  • 對比不必定徹底正確,有可能會遺漏一些細節,須要進行檢查


python database.py db migrate -m 'initial migration'

更新數據庫

python database.py db upgrade

返回之前的版本

能夠根據history命令找到版本號,而後傳給downgrade命令:api

python app.py db history

輸出格式:<base> ->  版本號 (head), initial migration
  • 回滾到指定版本


python app.py db downgrade 版本號

實際操做順序:

  • 1.python 文件 db init
  • 2.python 文件 db migrate -m"版本名(註釋)"
  • 3.python 文件 db upgrade 而後觀察表結構
  • 4.根據需求修改模型
  • 5.python 文件 db migrate -m"新版本名(註釋)"
  • 6.python 文件 db upgrade 而後觀察表結構
  • 7.若返回版本,則利用 python 文件 db history查看版本號
  • 8.python 文件 db downgrade(upgrade) 版本號

 

信號機制

Flask信號機制

  • Flask信號(signals, or event hooking)容許特定的發送端通知訂閱者發生了什麼(既然知道發生了什麼,那咱們能夠知道接下來該作什麼了)。
  • Flask提供了一些信號(核心信號)且其它的擴展提供更多的信號。
  • 信號依賴於Blinker庫。
    pip install blinker
  • flask內置信號列表:http://docs.jinkan.org/docs/flask/api.html#id17
    template_rendered = _signals.signal('template-rendered') request_started = _signals.signal('request-started') request_finished = _signals.signal('request-finished') request_tearing_down = _signals.signal('request-tearing-down') got_request_exception = _signals.signal('got-request-exception') appcontext_tearing_down = _signals.signal('appcontext-tearing-down') appcontext_pushed = _signals.signal('appcontext-pushed') appcontext_popped = _signals.signal('appcontext-popped') message_flashed = _signals.signal('message-flashed') 

信號應用場景

Flask-User 這個擴展中定義了名爲 user_logged_in 的信號,當用戶成功登入以後,這個信號會被髮送。咱們能夠訂閱該信號去追蹤登陸次數和登陸IP:bash

from flask import request from flask_user.signals import user_logged_in @user_logged_in.connect_via(app) def track_logins(sender, user, **extra): user.login_count += 1 user.last_login_ip = request.remote_addr db.session.add(user) db.session.commit() 

Flask-SQLAlchemy 信號支持

在 Flask-SQLAlchemy 模塊中,0.10 版本開始支持信號,能夠鏈接到信號來獲取到底發生什麼了的通知。存在於下面兩個信號:session

  • models_committed
    • 這個信號在修改的模型提交到數據庫時發出。發送者是發送修改的應用,模型 和 操做描述符 以 (model, operation) 形式做爲元組,這樣的元組列表傳遞給接受者的 changes 參數。
    • 該模型是發送到數據庫的模型實例,當一個模型已經插入,操做是 'insert' ,而已刪除是 'delete' ,若是更新了任何列,會是 'update' 。
  • before_models_committed
    • 除了恰好在提交發送前發生,與 models_committed 徹底相同。
from flask_sqlalchemy import models_committed # 給 models_committed 信號添加一個訂閱者,即爲當前 app @models_committed.connect_via(app) def models_committed(a, changes): print(a, changes) 

對數據庫進行增刪改進行測試

相關文章
相關標籤/搜索