将sqlite 3与Flask一起使用¶
在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()
现在,要使用数据库,应用程序必须有一个活动的应用程序上下文(如果有一个请求正在运行,则始终为true),或者创建一个应用程序上下文本身。在那一点上 get_db
函数可用于获取当前数据库连接。只要上下文被破坏,数据库连接就会终止。
例子::
@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模块返回此数据库连接的dict,这是更好的处理方法。更简单的说,我们可以把它放在 get_db
取而代之的是:
db.row_factory = sqlite3.Row
这将使用行对象而不是dict返回查询结果。这些是 namedtuple
所以我们可以通过索引或键访问它们。例如,假设我们有一个 sqlite3.Row
调用 r
为了行 id
, FirstName
, LastName
和 MiddleInitial
::
>>> # 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 Injections .
初始模式¶
关系数据库需要模式,因此应用程序通常 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()