在 Flask 中使用 SQLite 3 — Flask 文档

来自菜鸟教程
Flask/docs/1.1.x/patterns/sqlite3
跳转至:导航、​搜索

在 Flask 中使用 SQLite 3

在 Flask 中,您可以轻松实现按需打开数据库连接并在上下文终止时(通常在请求结束时)关闭它们。

这是一个简单的示例,说明如何将 SQLite 3 与 Flask 结合使用:

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()

现在,要使用数据库,应用程序必须有一个活动的应用程序上下文(如果有请求在执行,则始终为真)或创建应用程序上下文本身。 此时可以使用 get_db 函数来获取当前的数据库连接。 每当上下文被破坏时,数据库连接将被终止。

注意:如果您使用 Flask 0.9 或更早版本,则需要使用 flask._app_ctx_stack.top 而不是 g,因为 flask.g 对象绑定到请求而不是应用程序上下文。

例子:

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

笔记

请记住,拆卸请求和 appcontext 函数始终会执行,即使前请求处理程序失败或从未执行过。 因此,在关闭数据库之前,我们必须确保数据库在此处。


按需连接

这种方法(第一次使用时连接)的好处是只有在真正需要时才会打开连接。 如果您想在请求上下文之外使用此代码,您可以通过手动打开应用程序上下文在 Python shell 中使用它:

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 模块返回此数据库连接的 dicts,这更好处理。 更简单的是,我们可以把它放在 get_db 中:

db.row_factory = sqlite3.Row

这将使用 Row 对象而不是 dicts 来返回查询结果。 这些是 namedtuple s,所以我们可以通过索引或键来访问它们。 例如,假设我们有一个名为 rsqlite3.Row 用于行 idFirstNameLastNameMiddleInitial ]:

>>> # 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 shell 创建这样的数据库:

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