FlaskでのSQLite3の使用—Flaskのドキュメント

提供:Dev Guides
< FlaskFlask/docs/1.0.x/patterns/sqlite3
移動先:案内検索

FlaskでSQLite3を使用する

Flaskでは、データベース接続をオンデマンドで開き、コンテキストが終了したときに(通常はリクエストの最後に)閉じるように簡単に実装できます。

以下は、FlaskでSQLite3を使用する方法の簡単な例です。

import sqlite3
from flask import g

DATABASE = '/path/to/database.db'

def get_db():
    db = getattr(g, '_database', None)
    if db is None:
        db = g._database = sqlite3.connect(DATABASE)
    return db

@app.teardown_appcontext
def close_connection(exception):
    db = getattr(g, '_database', None)
    if db is not None:
        db.close()

ここで、データベースを使用するには、アプリケーションにアクティブなアプリケーションコンテキスト(実行中の要求がある場合は常にtrue)があるか、アプリケーションコンテキスト自体を作成する必要があります。 その時点で、get_db関数を使用して現在のデータベース接続を取得できます。 コンテキストが破棄されるたびに、データベース接続は終了します。

注:Flask 0.9以前を使用する場合は、 Flask.g オブジェクトがアプリケーションコンテキストではなくリクエストにバインドされているため、gではなくflask._app_ctx_stack.topを使用する必要があります。

例:

@app.route('/')
def index():
    cur = get_db().cursor()
    ...

ノート

before-requestハンドラーが失敗した場合や実行されなかった場合でも、ティアダウン要求関数とappcontext関数は常に実行されることに注意してください。 このため、データベースを閉じる前に、データベースがそこにあることを確認する必要があります。


オンデマンド接続

このアプローチ(最初の使用時に接続する)の利点は、本当に必要な場合にのみ接続を開くことです。 このコードをリクエストコンテキストの外部で使用する場合は、アプリケーションコンテキストを手動で開くことにより、Pythonシェルで使用できます。

with app.app_context():
    # now you can use get_db()

簡単なクエリ

これで、各リクエスト処理関数で get_db()にアクセスして、現在開いているデータベース接続を取得できます。 SQLiteの操作を簡素化するには、行ファクトリ関数が役立ちます。 これは、データベースから返されたすべての結果に対して実行され、結果を変換します。 たとえば、タプルの代わりに辞書を取得するために、これを上記で作成したget_db関数に挿入できます。

def make_dicts(cursor, row):
    return dict((cursor.description[idx][0], value)
                for idx, value in enumerate(row))

db.row_factory = make_dicts

これにより、sqlite3モジュールはこのデータベース接続のdictを返すようになり、処理がはるかに簡単になります。 さらに簡単に言うと、代わりにこれをget_dbに配置できます。

db.row_factory = sqlite3.Row

これは、クエリの結果を返すためにdictではなくRowオブジェクトを使用します。 これらはnamedtupleであるため、インデックスまたはキーのいずれかでアクセスできます。 たとえば、行idFirstNameLastName、およびMiddleInitialrというsqlite3.Rowがあるとします。 ]:

>>> # You can get values based on the row's name
>>> r['FirstName']
John
>>> # Or, you can get them based on index
>>> r[1]
John
# Row objects are also iterable:
>>> for value in r:
...     print(value)
1
John
Doe
M

さらに、カーソルの取得、実行、および結果のフェッチを組み合わせたクエリ関数を提供することをお勧めします。

def query_db(query, args=(), one=False):
    cur = get_db().execute(query, args)
    rv = cur.fetchall()
    cur.close()
    return (rv[0] if rv else None) if one else rv

この便利な小さな関数を行ファクトリと組み合わせると、生のカーソルと接続オブジェクトを使用するよりもはるかに快適にデータベースを操作できます。

使用方法は次のとおりです。

for user in query_db('select * from users'):
    print user['username'], 'has the id', user['user_id']

または、単一の結果が必要な場合:

user = query_db('select * from users where username = ?',
                [the_username], one=True)
if user is None:
    print 'No such user'
else:
    print the_username, 'has the id', user['user_id']

変数部分をSQLステートメントに渡すには、ステートメントで疑問符を使用し、引数をリストとして渡します。 SQLインジェクションを使用してアプリケーションを攻撃する可能性があるため、文字列形式でSQLステートメントに直接追加しないでください。


初期スキーマ

リレーショナルデータベースにはスキーマが必要なため、アプリケーションはデータベースを作成する schema.sql ファイルを出荷することがよくあります。 そのスキーマに基づいてデータベースを作成する関数を提供することをお勧めします。 この関数はあなたのためにそれをすることができます:

def init_db():
    with app.app_context():
        db = get_db()
        with app.open_resource('schema.sql', mode='r') as f:
            db.cursor().executescript(f.read())
        db.commit()

次に、Pythonシェルからそのようなデータベースを作成できます。

>>> from yourapplication import init_db
>>> init_db()