Использование 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()
Теперь, для использования базы данных, приложение должно иметь активный контекст приложения (что всегда верно, если запрос находится в обработке) или создать контекст приложения самостоятельно. В этот момент можно использовать функцию get_db для получения текущего подключения к базе данных. При каждом уничтожении контекста подключение к базе данных будет закрыто.
Примечание: если вы используете Flask 0.9 или более раннюю версию, вам необходимо использовать flask._app_ctx_stack.top вместо g, так как объект flask.g был связан с запросом, а не контекстом приложения.
Пример:
@app.route('/')
def index():
cur = get_db().cursor()
...
Примечание
Пожалуйста, имейте в виду, что функции обработки завершения запроса и контекста приложения всегда выполняются, даже если обработчик перед запросом завершился неудачно или не был выполнен. Из-за этого нам нужно убедиться, что база данных существует до её закрытия.
Подключение по требованию
Преимущество этого подхода (подключение при первом использовании) заключается в том, что подключение будет открываться только при необходимости. Если вы хотите использовать этот код вне контекста запроса, вы можете использовать его в оболочке 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 возвращать словари для этого подключения к базе данных, с которыми работать намного удобнее. Ещё проще, мы можем поместить это в get_db вместо этого:
db.row_factory = sqlite3.Row
Это будет использовать объекты Row вместо словарей для возврата результатов запросов. Это 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-инъекций.
Инициализация схем
Реляционным базам данных необходимы схемы, поэтому приложения часто поставляются с файлом 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()
© 2007–2020 Pallets
Licensed under the BSD 3-clause License.
https://flask.palletsprojects.com/en/1.0.x/patterns/sqlite3/