溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Flask中sqlalchemy模塊的詳細(xì)簡(jiǎn)介分析

發(fā)布時(shí)間:2020-08-05 11:00:40 來源:億速云 閱讀:160 作者:清晨 欄目:編程語言

這篇文章給大家分享的是有關(guān)Flask中sqlalchemy模塊的詳細(xì)簡(jiǎn)介分析的內(nèi)容。小編覺得挺實(shí)用的,因此分享給大家做個(gè)參考。一起跟隨小編過來看看吧。

一、安裝

$ pip install flask-sqlalchemy

二、配置

配置選項(xiàng)列表 :

Flask中sqlalchemy模塊的詳細(xì)簡(jiǎn)介分析

SQLALCHEMY_NATIVE_UNICODE | 可以用于顯式禁用原生 unicode 支持。當(dāng)使用 不合適的指定無編碼的數(shù)據(jù)庫默認(rèn)值時(shí),這對(duì)于 一些數(shù)據(jù)庫適配器是必須的(比如 Ubuntu 上某些版本的 PostgreSQL )。|

| SQLALCHEMY_POOL_SIZE | 數(shù)據(jù)庫連接池的大小。默認(rèn)是引擎默認(rèn)值(通常 是 5 ) |

| SQLALCHEMY_POOL_TIMEOUT | 設(shè)定連接池的連接超時(shí)時(shí)間。默認(rèn)是 10 。 |

| SQLALCHEMY_POOL_RECYCLE | 多少秒后自動(dòng)回收連接。這對(duì) MySQL 是必要的, 它默認(rèn)移除閑置多于 8 小時(shí)的連接。注意如果 使用了 MySQL , Flask-SQLALchemy 自動(dòng)設(shè)定這個(gè)值為 2 小時(shí)。|

app.config["SQLALCHEMY_DATABASE_URI"] = DATABASE_URI
app.config["SQLALCHEMY_COMMIT_ON_TEARDOWN"] = True/False  # 每次請(qǐng)求結(jié)束后都會(huì)自動(dòng)提交數(shù)據(jù)庫中的變動(dòng).
 
app.config[""] = 
app.config[""] = 
app.config[""] = 
app.config[""] = 
 
DATABASE_URI :
    mysql : mysql://username:password@hostname/database
 
    pgsql : postgresql://username:password@hostname/database
 
    sqlite(linux)  : sqlite:////absolute/path/to/database
 
    sqlite(windows) : sqlite:///c:/absolute/path/to/database

三、初始化示例

from flask import Flask
from flask_sqlalchemy import SQLAlchemy
base_dir = os.path.abspath(os.path.dirname(__file__))
 
app = Flask(__name__)
 
app.config["SQLALCHEMY_DATABASE_URI"] = 'sqlite:///' + os.path.join(base_dir, 'data.sqlite')
app.config["SQLALCHEMY_COMMIT_ON_TEARDOWN"] = True
 
db = SQLAlchemy(app)

四、定義模型

模型 表示程序使用的持久化實(shí)體. 在 ORM 中, 模型一般是一個(gè) Python 類, 類中的屬性對(duì)應(yīng)數(shù)據(jù)庫中的表.

Flaks-SQLAlchemy 創(chuàng)建的數(shù)據(jù)庫實(shí)例為模型提供了一個(gè)基類以及一些列輔助類和輔助函數(shù), 可用于定義模型的結(jié)構(gòu).

db.Model    # 創(chuàng)建模型,
db.Column   # 創(chuàng)建模型屬性.

模型屬性類型 :

Flask中sqlalchemy模塊的詳細(xì)簡(jiǎn)介分析

常用 SQLAlchemy 列選項(xiàng)

Flask中sqlalchemy模塊的詳細(xì)簡(jiǎn)介分析

示例 :

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):
        """非必須, 用于在調(diào)試或測(cè)試時(shí), 返回一個(gè)具有可讀性的字符串表示模型."""
        return '<Role %r>' % self.name
 
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):          
        """非必須, 用于在調(diào)試或測(cè)試時(shí), 返回一個(gè)具有可讀性的字符串表示模型."""
        return '<Role %r>' % self.username

五、關(guān)系

關(guān)系型數(shù)據(jù)庫使用關(guān)系把不同表中的行聯(lián)系起來。

常用 SQLAlchemy 關(guān)系選項(xiàng):

Flask中sqlalchemy模塊的詳細(xì)簡(jiǎn)介分析

(1)一對(duì)多

原理 : 在 “多” 這一側(cè)加入一個(gè)外鍵, 指定 “一” 這一側(cè)聯(lián)結(jié)的記錄.

示例代碼 : 一個(gè)角色可屬于多個(gè)用戶, 而每個(gè)用戶只能有一個(gè)角色.

class Role(db.Model):
    # ...
    users = db.relationship('User', backref='role')
 
class User(db.Model):
    # ...
    role_id = db.Column(db.Integer, db.ForeignKey('roles.id'))  # 外鍵關(guān)系.
 
 
###############
db.ForeignKey('roles.id') : 外鍵關(guān)系,
 
Role.users = db.relationship('User', backref='role') : 代表 外鍵關(guān)系的 面向?qū)ο笠暯? 對(duì)于一個(gè) Role 類的實(shí)例, 
其 users 屬性將返回與角色相關(guān)聯(lián)的用戶組成的列表. 
    db.relationship() 第一個(gè)參數(shù)表示這個(gè)關(guān)系的另一端是哪個(gè)模型. 
    backref 參數(shù), 向 User 模型添加了一個(gè) role 數(shù)據(jù)屬性, 從而定義反向關(guān)系.  這一屬性可替代 role_id 訪問 Role 模型, 
    此時(shí)獲取的是模型對(duì)象, 而不是外鍵的值.

(2)多對(duì)多

最復(fù)雜的關(guān)系類型,需要用到第三章表,即關(guān)聯(lián)表,這樣多對(duì)多關(guān)系可以分解成原表和關(guān)聯(lián)表之間的兩個(gè)一對(duì)多關(guān)系。

查詢多對(duì)多關(guān)系分兩步 : 遍歷兩個(gè)關(guān)系來獲取查詢結(jié)果。

代碼示例:

registrations = db.Table("registrations",
                         db.Column("student_id", db.Integer, db.ForeignKey("students.id")),
                         db.Column("class_id", db.Integer, db.ForeignKey("classes.id"))
                         )
 
class Student(db.Model):
    __tablename__ = "students"
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String)
    classes = db.relationship("Class",
                              secondary=registrations,
                              backref=db.backref("students", lazy="dynamic"),
                              lazy="dynamic")
 
class Class(db.Model):
    __tablename__ = "classes"
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String)

多對(duì)多關(guān)系仍然使用定義一對(duì)多關(guān)系的 db.relationship() 方法進(jìn)行定義, 但在多對(duì)多關(guān)系中, 必須把 secondary 參數(shù)設(shè)為關(guān)聯(lián)表。

多對(duì)多關(guān)系可以在任何一個(gè)類中定義, backref 參數(shù)會(huì)處理好關(guān)系的另一側(cè)。

關(guān)聯(lián)表就是一個(gè)簡(jiǎn)單的表, 不是模型, SQLAlchemy 會(huì)自動(dòng)接管這個(gè)表。

classes 關(guān)系使用列表語義, 這樣處理多對(duì)多關(guān)系比較簡(jiǎn)單。

Class 模型的 students 關(guān)系有 參數(shù) db.backref() 定義. 這個(gè)關(guān)系還指定了 lazy 參數(shù), 所以, 關(guān)系兩側(cè)返回的查詢都可接受額外的過濾器。

自引用關(guān)系

自引用關(guān)系可以理解為多對(duì)多關(guān)系的特殊形式 : 多對(duì)多關(guān)系的兩邊由兩個(gè)實(shí)體變?yōu)橐粋€(gè)實(shí)體。

高級(jí)多對(duì)多關(guān)系

使用多對(duì)多關(guān)系時(shí),往往需要存儲(chǔ)所聯(lián)兩個(gè)實(shí)體之間的額外信息。這種信息只能存儲(chǔ)在關(guān)聯(lián)表中,對(duì)用戶之間的關(guān)注來說,可以存儲(chǔ)用戶關(guān)注另一個(gè)用戶的日期,這樣就能按照時(shí)間順序列出所有關(guān)注者。

為了能在關(guān)系中處理自定義的數(shù)據(jù),必須提升關(guān)聯(lián)表的地位,使其變成程序可訪問的模型。

關(guān)注關(guān)聯(lián)表模型實(shí)現(xiàn):

class Follow(db.Model):
    __tablename__ = "follows"
    follower_id = db.Column(db.Integer, db.ForeignKey("users.id"), primary_key=True)
    followed_id = db.Column(db.Integer, db.ForeignKey("users.id"), primary_key=True)
    timestamp = db.Column(db.DateTime, default=datetime.utcnow)
 
# SQLAlchemy 不能直接使用這個(gè)關(guān)聯(lián)表, 因?yàn)槿绻@個(gè)做程序就無法訪問其中的自定義字段. 相反的, 要把這個(gè)多對(duì)多關(guān)系的左右
兩側(cè)拆分成兩個(gè)基本的一對(duì)多關(guān)系, 而且要定義成標(biāo)準(zhǔn)的關(guān)系。

使用兩個(gè)一對(duì)多關(guān)系實(shí)現(xiàn)的多對(duì)多關(guān)系:

class User(UserMixin, db.Model):
    # ...
    followd = db.relationship("Follow",
                              foreign_keys=[Follow.follower_id],
                              backref=db.backref("follower", lazy="joined"),
                              lazy="dynamic",
                              cascade="all, delete-orphan")
    followrs = db.relationship("Follow",
                              foreign_keys=[Follow.followed_id],
                              backref=db.backref("followed", lazy="joined"),
                              lazy="dynamic",
                              cascade="all, delete-orphan")
# 這段代碼中, followed 和 follower 關(guān)系都定義為 單獨(dú)的 一對(duì)多關(guān)系. 
# 注意: 為了消除外鍵歧義, 定義關(guān)系是必須使用可選參數(shù) foreign_keys 指定的外鍵. 而且 db.backref() 參數(shù)并不是指定這兩個(gè)
關(guān)系之間的引用關(guān)系, 而是回引 Follow 模型. 回引中的 lazy="joined" , 該模式可以實(shí)現(xiàn)立即從連接查詢中加載相關(guān)對(duì)象.
# 這兩個(gè)關(guān)系中, user 一側(cè)設(shè)定的 lazy 參數(shù)作用不一樣. lazy 參數(shù)都在 "一" 這一側(cè)設(shè)定, 返回的結(jié)果是 "多" 這一側(cè)中的記錄. 
dynamic 參數(shù), 返回的是查詢對(duì)象.
# cascade 參數(shù)配置在父對(duì)象上執(zhí)行的操作相關(guān)對(duì)象的影響. 比如, 層疊對(duì)象可設(shè)定為: 將用戶添加到數(shù)據(jù)庫會(huì)話后, 要自定把所有
關(guān)系的對(duì)象都添加到會(huì)話中. 刪除對(duì)象時(shí), 默認(rèn)的層疊行為是把對(duì)象聯(lián)結(jié)的所有相關(guān)對(duì)象的外鍵設(shè)為空值. 但在關(guān)聯(lián)表中, 刪除記錄
后正確的行為是把執(zhí)行該記錄的實(shí)體也刪除, 因?yàn)檫@樣才能有效銷毀聯(lián)結(jié). 這就是 層疊選項(xiàng)值 delete-orphan 的作用. 設(shè)為 all, 
delete-orphan 的意思是啟動(dòng)所有默認(rèn)層疊選項(xiàng), 并且還要?jiǎng)h除孤兒記錄。

(3)一對(duì)一

可以看做特殊的 一對(duì)多 關(guān)系. 但調(diào)用 db.relationship() 時(shí) 要把 uselist 設(shè)置 False, 把 多變?yōu)?一。

(4)多對(duì)一

將一對(duì)多關(guān)系,反過來即可,也是一對(duì)多關(guān)系。

六、數(shù)據(jù)庫操作

(1)創(chuàng)建數(shù)據(jù)庫及數(shù)據(jù)表

創(chuàng)建數(shù)據(jù)庫

db.create_all()

示例 :

$ python myflask.py shell
> from myflask import db
> db.create_all()

如果使用 sqlite , 會(huì)在 SQLALCHEMY_DATABASE_URI 指定的目錄下 多一個(gè)文件,文件名為該配置中的文件名。

如果數(shù)據(jù)庫表已經(jīng)存在于數(shù)據(jù)庫中, 那么 db.create_all() 不會(huì)創(chuàng)建或更新這個(gè)表。

更新數(shù)據(jù)庫

方法一 :

先刪除, 在創(chuàng)建 –> 原有數(shù)據(jù)庫中的數(shù)據(jù), 都會(huì)消失.

> db.drop_all()
> db.create_all()

方法二 :

數(shù)據(jù)庫遷移框架 : 可以跟自動(dòng)數(shù)據(jù)庫模式的變化,然后增量式的把變化應(yīng)用到數(shù)據(jù)庫中。

SQLAlchemy 的主力開發(fā)人員編寫了一個(gè) 遷移框架 Alembic, 除了直接使用 Alembic wait, Flask 程序還可使用 Flask-Migrate 擴(kuò)展, 該擴(kuò)展對(duì) Alembic 做了輕量級(jí)包裝, 并集成到 Flask-Script 中, 所有操作都通過 Flaks-Script 命令完成。

① 安裝 Flask-Migrate

$ pip install flask-migrate

② 配置

from flask_migrate import Migrate, MigrateCommand
 
# ...
migrate = Migrate(app, db)
manager.add_command('db', MigrateCommand)

③ 數(shù)據(jù)庫遷移

a. 使用 init 自命令創(chuàng)建遷移倉(cāng)庫.

$ python myflask.py db init # 該命令會(huì)創(chuàng)建 migrations 文件夾, 所有遷移腳本都存在其中.

b. 創(chuàng)建數(shù)據(jù)路遷移腳本.
    $ python myflask.py db revision     # 手動(dòng)創(chuàng)建 Alemic 遷移
    創(chuàng)建的遷移只是一個(gè)骨架, upgrade() 和 downgrade() 函數(shù)都是空的. 開發(fā)者需要使用 Alembic 提供的 Operations 對(duì)象
    指令實(shí)現(xiàn)具體操作.
 
    $ python myflask.py db migrate -m COMMONT    # 自動(dòng)創(chuàng)建遷移.
    自動(dòng)創(chuàng)建的遷移會(huì)根據(jù)模型定義和數(shù)據(jù)庫當(dāng)前的狀態(tài)之間的差異生成 upgrade() 和 downgrade() 函數(shù)的內(nèi)容.
 
    ** 自動(dòng)創(chuàng)建的遷移不一定總是正確的, 有可能漏掉一些細(xì)節(jié), 自動(dòng)生成遷移腳本后一定要進(jìn)行檢查.
 
 
c. 更新數(shù)據(jù)庫
    $ python myflask.py db upgrade     # 將遷移應(yīng)用到數(shù)據(jù)庫中.

(2)插入行

模型的構(gòu)造函數(shù),接收的參數(shù)是使用關(guān)鍵字參數(shù)指定的模型屬性初始值。注意,role 屬性也可使用,雖然他不是真正的數(shù)據(jù)庫列,但卻是一對(duì)多關(guān)系的高級(jí)表示。這些新建對(duì)象的 id 屬性并沒有明確設(shè)定,因?yàn)橹麈I是由 Flask-SQLAlchemy 管理的?,F(xiàn)在這些對(duì)象只存在于 Python 解釋器中,尚未寫入數(shù)據(jù)庫。

>> from myflask import db, User, Role
>> db.create_all()
>> admin_role = Role(name="Admin")
>> mod_role = Role(name="Moderator")
>> user_role = Role(name="User")
>> user_john = User(username="john", role=admin_role)
>> user_susan = User(username="susan", role=mod_role)
>> user_david = User(username="david", role=user_role)
>> admin_role.name
'Admin'
>> admin_role.id
None
---------
>> db.session.add_all([admin_role, mod_role, user_role, user_john, user_susan, user_david])  # 把對(duì)象添加到會(huì)話中.
>> db.session.commit()      # 把對(duì)象寫入數(shù)據(jù)庫, 使用 commit() 提交會(huì)話.

(3)修改行

>> admin_role = "Administrator"
>> db.session.add(admin_role)
>> db.session.commit()

(4)刪除行

>> db.session.delete(mod_role)
>> db.session.commit()

(5)查詢行

Flask-SQLAlchemy 為每個(gè)模型類都提供了 query 對(duì)象.

獲取表中的所有記錄

>> Role.query.all()
  [<Role u'Admin'>, <Role u'Moderator'>, <Role u'User'>]
>> User.query.all()
  [<Role u'john'>, <Role u'susan'>, <Role u'david'>]

查詢過濾器

filter_by() 等過濾器在 query 對(duì)象上調(diào)用, 返回一個(gè)更精確的 query 對(duì)象. 多個(gè)過濾器可以一起調(diào)用, 直到獲取到所需的結(jié)果.

>> User.query.filter_by(role=user_role).all()   # 以列表形式,返回所有結(jié)果,
>> User.query.filter_by(role=user_role).first() # 返回結(jié)果中的第一個(gè).

filter() 對(duì)查詢結(jié)果過濾,比”filter_by()”方法更強(qiáng)大,參數(shù)是布爾表達(dá)式

# WHERE age<20
users = User.query.filter(User.age<20)
# WHERE name LIKE 'J%' AND age<20
users = User.query.filter(User.name.startswith('J'), User.age<20)

查詢過濾器 :

Flask中sqlalchemy模塊的詳細(xì)簡(jiǎn)介分析

查詢執(zhí)行函數(shù) :

Flask中sqlalchemy模塊的詳細(xì)簡(jiǎn)介分析

first_or_404() | 返回查詢的第一個(gè)結(jié)果,如果沒有結(jié)果,則終止請(qǐng)求,返回 404 錯(cuò)誤響應(yīng) | |

| get() | 返回指定主鍵對(duì)應(yīng)的行,如果沒有對(duì)應(yīng)的行,則返回 None |

get_or_404() | 返回指定主鍵對(duì)應(yīng)的行,如果沒找到指定的主鍵,則終止請(qǐng)求,返回 404 | |錯(cuò)誤響應(yīng)

| count() | 返回查詢結(jié)果的數(shù)量 |

| paginate() | 返回一個(gè) Paginate 對(duì)象,它包含指定范圍內(nèi)的結(jié)果 |

(6)會(huì)話管理,事務(wù)管理

單個(gè)提交

>> db.session.add(ONE)
>> db.session.commit()

多個(gè)提交

>> db.session.add_all([LIST_OF_MEMBER])
>> db.session.commit()

刪除會(huì)話

>> db.session.delete(mod_role)
>> db.session.commit()

事務(wù)回滾 : 添加到數(shù)據(jù)庫會(huì)話中的所有對(duì)象都會(huì)還原到他們?cè)跀?shù)據(jù)庫時(shí)的狀態(tài).

>> db.session.rollback()

七、視圖函數(shù)中操作數(shù)據(jù)庫

@app.route('/', methods=['GET', 'POST'])
def index():
    form = NameForm()
    if form.validate_on_submit():
        user = User.query.filter_by(username=form.name.data).first()
        if user is None:
            user = User(username=form.name.data)
            db.session.add(user)
            session["known"] = False
        else:
            session["known"] = True
        session["name"] = form.name.data
        form.name.data = ""             # why empty it ?
        return redirect(url_for("index"))
    return render_template("index.html", current_time=datetime.utcnow(), form=form, name=session.get("name"), 
    known=session.get("known"))

八、分頁對(duì)象 Pagination

1. paginate() 方法

paginate() 方法的返回值是一個(gè) Pagination 類對(duì)象,該類在 Flask-SQLAlchemy 中定義,用于在模板中生成分頁鏈接。

paginate(頁數(shù)[,per_page=20, error_out=True])
    頁數(shù) : 唯一必須指定的參數(shù),
    per_page : 指定每頁現(xiàn)實(shí)的記錄數(shù)量, 默認(rèn) 20.
    error_out : True 如果請(qǐng)求的頁數(shù)超出了返回, 返回 404 錯(cuò)誤; False 頁數(shù)超出范圍時(shí)返回一個(gè),空列表.

示例代碼:

@main.route("/", methods=["GET", "POST"])
def index():
    # ...
    page = request.args.get('page', 1, type=int)    # 渲染的頁數(shù), 默認(rèn)第一頁, type=int 保證參數(shù)無法轉(zhuǎn)換成整數(shù)時(shí), 
    返回默認(rèn)值.
    pagination = Post.query.order_by(Post.timestamp.desc()).paginate(page, per_page=current_app.config
    ["FLASKY_POSTS_PER_PAGE"], error_out=False)
    posts = pagination.items
    return render_template('index.html', form=form, posts=posts,pagination=pagination)

2. 分頁對(duì)象的屬性及方法:

Flask_SQLAlchemy 分頁對(duì)象的屬性:

Flask中sqlalchemy模塊的詳細(xì)簡(jiǎn)介分析

在分頁對(duì)象可調(diào)用的方法:

Flask中sqlalchemy模塊的詳細(xì)簡(jiǎn)介分析

3. 在模板中與 BootStrap 結(jié)合使用示例

使用 Flaks-SQLAlchemy 的分頁對(duì)象與 Bootstrap 中的分頁 CSS, 可以輕松的構(gòu)造出一個(gè) 分頁導(dǎo)航.

分頁模板宏 _macros.html : 創(chuàng)建一個(gè) Bootstrap 分頁元素, 即一個(gè)有特殊樣式的無序列表.

{% macro pagination_widget(pagination,endpoint) %}
<ul class="pagination">
    <li {% if not pagination.has_prev %} class="disabled" {% endif %}>
        <a href="{% if pagination.has_prev %}{{url_for(endpoint, page=paginatin.page - 1, **kwargs)}}{% else %}
        #{% endif %}">
            &laquo;
        </a>
    </li>
    {% for p in pagination,.iter_pages() %}
        {% if p %}
            {% if p == pagination.page %}
            <li class="active">
                <a href="{{ url_for(endpoint, page=p, **kwargs) }}">{{p}}</a>
            </li>
            {% else %}
            <li>
                <a href="{{ url_for(endpoint, page = p, **kwargs) }}">{{p}}</a>
            </li>
            {% endif %}
        {% else %}
        <li class="disabled"><a href="#">&hellip;</a> </li>
        {% endif %}
    {% endfor %}
    <li {% if not pagination.has_next %} class="disabled" {% endif%}>
        <a href="{% if paginatin.has_next %}{{ url_for(endpoint, page=pagination.page+1, **kwargs) }}{% else %}
        #{% endif %}">
            &raquo;
        </a>
    </li>
</ul>
{% endmacro %}

導(dǎo)入使用分頁導(dǎo)航

{% extends "base.html" %}
{% import "_macros.html" as macros %}
...
<div class="pagination">
    {{ macro.pagination_widget(pagination, ".index")}}
</div>

九、監(jiān)聽事件

1. set 事件

示例代碼 :

from markdown import markdown
import bleach
class Post(db.Model):
    # ...
    body = db.Colume(db.Text)
    body_html = db.Column(db.Text)
    # ...
    @staticmethod
    def on_changeed_body(target, value, oldvalue, initiator):
        allowed_tags = ["a", "abbr", "acronym", "b", "blockquote", "code", "em",
                        "i", "li", "ol", "pre", "strong", "ul", "h2", "h3","h4","h5","p"]
        target.body_html = bleach.linkify(bleach.clean(markdown(value, output_format="html"), tags=allowed_tags, 
        strip=True))
db.event.listen(Post.body, "set", Post.on_changeed_body) 
# on_changed_body 函數(shù)注冊(cè)在 body 字段上, 是 SQLIAlchemy "set" 事件的監(jiān)聽程序, 
# 這意味著只要這個(gè)類實(shí)例的 body 字段設(shè)了新值, 函數(shù)就會(huì)自動(dòng)被調(diào)用. 
# on_changed_body 函數(shù)把 body 字段中的文本渲染成 HTML 格式, 
# 結(jié)果保存在 body_html 中, 自動(dòng)高效的完成 Markdown 文本到 HTML 的轉(zhuǎn)換

十、記錄慢查詢

十一、Binds 操作多個(gè)數(shù)據(jù)庫

十二、其他

1. ORM 在查詢時(shí)做初始化操作

當(dāng) SQLIAlchemy ORM 從數(shù)據(jù)庫查詢數(shù)據(jù)時(shí), 默認(rèn)不調(diào)用__init__ 方法, 其底層實(shí)現(xiàn)了 Python 類的 __new__() 方法, 直接實(shí)現(xiàn) 對(duì)象實(shí)例化, 而不是通過 __init__ 來實(shí)例化對(duì)象.

如果需要在查詢時(shí), 依舊希望實(shí)現(xiàn)一些初始化操作, 可以使用 orm.reconstructor() 裝飾器或 實(shí)現(xiàn) InstanceEvents.load() 監(jiān)聽事件。

# orm.reconstructor
from sqlalchemy import orm
class MyMappedClass(object):
    def __init__(self, data):
        self.data = data
        # we need stuff on all instances, but not in the database.
        self.stuff = []
    @orm.reconstructor
    def init_on_load(self):
        self.stuff = []
# InstanceEvents.load()
from sqlalchemy import event
## standard decorator style
@event.listens_for(SomeClass, 'load')
def receive_load(target, context):
    "listen for the 'load' event"
    # ... (event handling logic) ...

如果只是希望在從數(shù)據(jù)庫查詢生成的對(duì)象中包含某些屬性, 也可以使用 property 實(shí)現(xiàn):

class AwsRegions(db.Model):
    name=db.Column(db.String(64))
    ...
    @property
    def zabbix_api(self):
        return ZabbixObj(zabbix_url)
    @zabbix_api.setter
    def zabbix_api(self):
        raise ValueError("zabbix can not be setted!")

感謝各位的閱讀!關(guān)于Flask中sqlalchemy模塊的詳細(xì)簡(jiǎn)介分析就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,讓大家可以學(xué)到更多知識(shí)。如果覺得文章不錯(cuò),可以把它分享出去讓更多的人看到吧!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI