Flask 在 Flask 中使用 SQLAIchemy

2021-08-11 10:00 更新

很多人更傾向于使用 SQLAlchemy 進行數(shù)據庫操作。在這種情況下,建議您使用 包的而不是模塊的方式組織您的應用代碼,并將所有的模型放置到一個單獨的模塊中 (大型應用)。盡管這并非必要,但是這么做將會讓程序的結構更加 明晰。

使用 SQLAlchemy 有四種常用的方法,我們在下面列出了這幾種方法的基本使用 框架:

Flask-SQLAlchemy 擴展

因為 SQLAlchemy 是一個常用的數(shù)據庫抽象層和數(shù)據庫關系映射包(ORM),并且需要 一點點設置才可以使用,因此存在一個 Flask 擴展幫助您操作它。如果您想要快速 開始使用,那么我們建議您使用這種方法。

您可以從 PyPI 下載到 Flask-SQLAlchemy

顯式調用

SQLAlchemy 中的 declarative 擴展是最新的使用 SQLAlchemy 的方法。它允許您 同時定義表和模型,就像 Django 一樣工作。除了下文所介紹的內容外,我們建議您 參考 declarative 擴展的官方文檔。

這是一個 database.py 模塊的例子:

from sqlalchemy import create_engine
from sqlalchemy.orm import scoped_session, sessionmaker
from sqlalchemy.ext.declarative import declarative_base

engine = create_engine('sqlite:////tmp/test.db', convert_unicode=True)
db_session = scoped_session(sessionmaker(autocommit=False,
                                         autoflush=False,
                                         bind=engine))
Base = declarative_base()
Base.query = db_session.query_property()

def init_db():
    # 在這里導入所有的可能與定義模型有關的模塊,這樣他們才會合適地
    # 在 metadata 中注冊。否則,您將不得不在第一次執(zhí)行 init_db() 時
    # 先導入他們。
    import yourapplication.models
    Base.metadata.create_all(bind=engine)

為了定義您的模型,僅僅構造一個上面代碼編寫的 Base 類的子類。如果您好奇 為何我們在這里不用擔心多線程的問題(就像我們在先前使用 g 對象操作 SQLite3 的例子一樣):那是因為 SQLAlchemy 已經在 scoped_session 類當中為我們完成了這些任務。

在您的應用當中以一個顯式調用 SQLAlchemy , 您只需要將如下代碼放置在您應用 的模塊中。Flask 將會在請求結束時自動移除數(shù)據庫會話:

from yourapplication.database import db_session

@app.teardown_request
def shutdown_session(exception=None):
    db_session.remove()

這是一個模型的例子(將代碼放入 models.py 或類似文件中):

from sqlalchemy import Column, Integer, String
from yourapplication.database import Base

class User(Base):
    __tablename__ = 'users'
    id = Column(Integer, primary_key=True)
    name = Column(String(50), unique=True)
    email = Column(String(120), unique=True)

    def __init__(self, name=None, email=None):
        self.name = name
        self.email = email

    def __repr__(self):
        return '<User %r>' % (self.name)

您可以使用 init_db 函數(shù)創(chuàng)建一個數(shù)據庫:

>>> from yourapplication.database import init_db
>>> init_db()

按照如下方式將數(shù)據實體插入數(shù)據庫:

>>> from yourapplication.database import db_session
>>> from yourapplication.models import User
>>> u = User('admin', 'admin@localhost')
>>> db_session.add(u)
>>> db_session.commit()

查詢代碼也很簡單:

>>> User.query.all()
[<User u'admin'>]
>>> User.query.filter(User.name == 'admin').first()
<User u'admin'>

手動實現(xiàn) ORM

手動實現(xiàn) ORM (對象關系映射) 相比前面的顯式調用方法,既有一些優(yōu)點,也有一些缺點。 主要差別在于這里的數(shù)據表和模型是分開定義的,然后再將其映射起來。這提供了更大的靈活性, 但是會增加了代碼量。通常來說它和上面顯式調用的工作的方式很相似,所以請確保您的應用已經 被合理分割到了包中的不同模塊中。

這是一個 database.py 模塊的例子:

from sqlalchemy import create_engine, MetaData
from sqlalchemy.orm import scoped_session, sessionmaker

engine = create_engine('sqlite:////tmp/test.db', convert_unicode=True)
metadata = MetaData()
db_session = scoped_session(sessionmaker(autocommit=False,
                                         autoflush=False,
                                         bind=engine))
def init_db():
    metadata.create_all(bind=engine)

與顯式調用相同,您需要在請求結束后關閉數(shù)據庫會話。將下面的代碼 放到您的應用程序模塊中:

from yourapplication.database import db_session

@app.teardown_request
def shutdown_session(exception=None):
    db_session.remove()

下面是一個數(shù)據表和模型的例子(將他們放到 models.py 當中):

from sqlalchemy import Table, Column, Integer, String
from sqlalchemy.orm import mapper
from yourapplication.database import metadata, db_session

class User(object):
    query = db_session.query_property()

    def __init__(self, name=None, email=None):
        self.name = name
        self.email = email

    def __repr__(self):
        return '<User %r>' % (self.name)

users = Table('users', metadata,
    Column('id', Integer, primary_key=True),
    Column('name', String(50), unique=True),
    Column('email', String(120), unique=True)
)
mapper(User, users)

查詢和插入操作和上面所給出的例子是一樣的。

SQL 抽象層

如果您僅用到數(shù)據庫系統(tǒng)和 SQL 抽象層,那么您只需要引擎部分:

from sqlalchemy import create_engine, MetaData

engine = create_engine('sqlite:////tmp/test.db', convert_unicode=True)
metadata = MetaData(bind=engine)

然后您就可以像上文的例子一樣聲明數(shù)據表,或者像下面這樣自動加載他們:

users = Table('users', metadata, autoload=True)

您可以使用 insert 方法插入數(shù)據,我們需要先獲取一個數(shù)據庫連接,這樣 我們就可以使用“事務”了:

>>> con = engine.connect()
>>> con.execute(users.insert(), name='admin', email='admin@localhost')

SQLAlchemy 將會為我們自動提交對數(shù)據庫的修改。

查詢數(shù)據可以直接通過數(shù)據庫引擎,也可以使用一個數(shù)據庫連接:

>>> users.select(users.c.id == 1).execute().first()
(1, u'admin', u'admin@localhost')

返回的結果也是字典樣式的元組:

>>> r = users.select(users.c.id == 1).execute().first()
>>> r['name']
u'admin'

您也可以將 SQL 語句的字符串傳入到 execute() 函數(shù)中:

>>> engine.execute('select * from users where id = :1', [1]).first()
(1, u'admin', u'admin@localhost')

更多 SQLAlchemy 相關信息,請參考 其網站.

以上內容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號