Использование 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 для получения текущего соединения с базой данных. Всякий раз, когда контекст уничтожается, соединение с базой данных будет закрыто.
Пример:
@app.route('/')
def index():
cur = get_db().cursor()
...
Примечание
Пожалуйста, помните, что функции teardown request и appcontext всегда выполняются, даже если обработчик перед запросом завершился неудачно или не был выполнен. Из-за этого нам необходимо убедиться, что база данных существует до её закрытия.
Подключение по требованию
Преимущество этого подхода (подключение при первом использовании) заключается в том, что соединение будет открыто только если это действительно необходимо. Если вы хотите использовать этот код вне контекста запроса, вы можете использовать его в оболочке 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()
© 2010 Pallets
Licensed under the BSD 3-clause License.
https://flask.palletsprojects.com/en/stable/patterns/sqlite3/