Использование 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()
Легкий поиск
Теперь в каждой функции обработки запроса вы можете получить доступ к g.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/0.12.x/patterns/sqlite3/