Использование 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–2022 Pallets
Licensed under the BSD 3-clause License.
https://flask.palletsprojects.com/en/2.1.x/patterns/sqlite3/