方法1: http://flask.pocoo.org/docs/tutorial/dbcon/ および http://flask.pocoo.org/docs/patterns/からの特別なgオブジェクトを使用するsqlite3 /
import sqlite3
from flask import g
DATABASE = '/path/to/database.db'
def connect_db():
return sqlite3.connect(DATABASE)
@app.before_request
def before_request():
g.db = connect_db()
@app.teardown_request
def teardown_request(exception):
if hasattr(g, 'db'):
g.db.close()
方法2: https://github.com/mitsuhiko/flask/blob/master/examples/flaskr/flaskr.py からMysterious _app_ctx_stackを使用する
from sqlite3 import dbapi2 as sqlite3
from flask import Flask, request, session, g, redirect, url_for, abort, \
render_template, flash, _app_ctx_stack
def get_db():
"""Opens a new database connection if there is none yet for the
current application context.
"""
top = _app_ctx_stack.top
if not hasattr(top, 'sqlite_db'):
top.sqlite_db = sqlite3.connect(app.config['DATABASE'])
return top.sqlite_db
@app.teardown_appcontext
def close_db_connection(exception):
"""Closes the database again at the end of the request."""
top = _app_ctx_stack.top
if hasattr(top, 'sqlite_db'):
top.sqlite_db.close()
どちらの方法が良いですか?違いはなんですか?
1つ目は、接続が不要な場合でも接続を取得するという問題があります。 2番目の方法には、サードパーティのフレームワークの内部で遊んでいるという欠点がありますが、かなり読みにくいです。
2つだけの場合、おそらく2つ目がより良い選択です。ルートを必要としないルートの接続を取得しないだけでなく、ルートの他のコードパスが必要な場合でも、必要のないコードパスを下る場合は接続を取得しません。 (たとえば、何らかのフォーム検証がある場合、検証に合格した場合にのみ接続が必要になります。検証が失敗しても接続は開かれません。)この設定で使用する前に接続を取得するだけです。
ただし、内部の混乱を避けることができ、それでもこれらすべての利点を得ることができます。個人的に、私は独自の小さなグローバルメソッドを作成しました。
import flask
import sqlite3
def request_has_connection():
return hasattr(flask.g, 'dbconn')
def get_request_connection():
if not request_has_connection():
flask.g.dbconn = sqlite3.connect(DATABASE)
# Do something to make this connection transactional.
# I'm not familiar enough with SQLite to know what that is.
return flask.g.dbconn
@app.teardown_request
def close_db_connection(ex):
if request_has_connection():
conn = get_request_connection()
# Rollback
# Alternatively, you could automatically commit if ex is None
# and rollback otherwise, but I question the wisdom
# of automatically committing.
conn.close()
次に、アプリ全体で、_get_request_connection
、あなたのget_db
関数。簡単で高効率。基本的に、両方の長所です。
振り返ってみると、これらがグローバルメソッドであるという事実を本当に嫌いますが、その理由はFlaskがどのように機能するかです。実際にスレッドローカルを指す「グローバル」を提供します。
Flask-SQLAlchemy をお勧めします。これは、Flaskで使用するためにSQLAlchemyを拡張し、さまざまなデータベースをサポートします。 (Flask-SQLAlchemyドキュメントの例)
セットアップ:
from flask import Flask
from flask.ext.sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:////tmp/test.db'
db = SQLAlchemy(app)
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(80), unique=True)
email = db.Column(db.String(120), unique=True)
def __init__(self, username, email):
self.username = username
self.email = email
def __repr__(self):
return '<User %r>' % self.username
これで、User
クラスをインポート/使用して、データベースのUserテーブルにアクセスできます。
新しいユーザーを作成します。
>>> from yourapplication import User
>>> admin = User('admin', '[email protected]')
>>> guest = User('guest', '[email protected]')
データベースにユーザーを追加します。
>>> db.session.add(admin)
>>> db.session.add(guest)
>>> db.session.commit()
データベースに既に存在するユーザーのクエリ:
>>> users = User.query.all()
[<User u'admin'>, <User u'guest'>]
>>> admin = User.query.filter_by(username='admin').first()
<User u'admin'>
方法1を使用します-より読みやすく、「ハック」が少なくなります。
方法2は、おそらくflask拡張機能の統合( 例 および app-ctx-stackの説明 )向けに設計されています。同様の効果があり、通常の場合は方法1を使用する必要があります。