Определение и доступ к базе данных¶
Приложение будет использовать базу данных SQLite для хранения пользователей и постов. Python поставляется со встроенной поддержкой SQLite в модуле sqlite3
.
SQLite удобен тем, что не требует установки отдельного сервера баз данных и встроен в Python. Однако, если одновременные запросы пытаются одновременно записывать данные в базу данных, они будут замедляться, поскольку каждая запись происходит последовательно. Небольшие приложения этого не заметят. Когда вы станете большим, вам, возможно, захочется перейти на другую базу данных.
В учебнике нет подробного описания SQL. Если вы не знакомы с ним, в документации по SQLite описано language.
Подключение к базе данных¶
Первое, что необходимо сделать при работе с базой данных SQLite (и большинством других библиотек баз данных Python), - это создать соединение с ней. Любые запросы и операции выполняются с использованием этого соединения, которое закрывается после завершения работы.
В веб-приложениях это соединение обычно привязано к запросу. Оно создается в определенный момент при обработке запроса и закрывается перед отправкой ответа.
import sqlite3
import click
from flask import current_app, g
def get_db():
if 'db' not in g:
g.db = sqlite3.connect(
current_app.config['DATABASE'],
detect_types=sqlite3.PARSE_DECLTYPES
)
g.db.row_factory = sqlite3.Row
return g.db
def close_db(e=None):
db = g.pop('db', None)
if db is not None:
db.close()
g
- это специальный объект, уникальный для каждого запроса. Он используется для хранения данных, к которым могут обращаться несколько функций во время выполнения запроса. Соединение сохраняется и используется повторно вместо создания нового соединения, если get_db
вызывается второй раз в том же запросе.
current_app
- это еще один специальный объект, который указывает на приложение Flask, обрабатывающее запрос. Поскольку вы использовали фабрику приложений, при написании остальной части кода объект приложения отсутствует. get_db
будет вызван, когда приложение будет создано и будет обрабатывать запрос, поэтому можно использовать current_app
.
sqlite3.connect()
устанавливает соединение с файлом, на который указывает ключ конфигурации DATABASE
. Этот файл еще не должен существовать, и не будет существовать, пока вы не инициализируете базу данных позже.
sqlite3.Row
указывает соединению возвращать строки, которые ведут себя как dicts. Это позволяет обращаться к столбцам по имени.
close_db
проверяет, было ли создано соединение, проверяя, было ли установлено g.db
. Если соединение существует, оно закрывается. Далее вы расскажете своему приложению о функции close_db
в фабрике приложений, чтобы она вызывалась после каждого запроса.
Создание таблиц¶
В SQLite данные хранятся в таблицах и столбцах. Они должны быть созданы до того, как вы сможете хранить и извлекать данные. Flaskr будет хранить пользователей в таблице user
, а посты в таблице post
. Создайте файл с командами SQL, необходимыми для создания пустых таблиц:
DROP TABLE IF EXISTS user;
DROP TABLE IF EXISTS post;
CREATE TABLE user (
id INTEGER PRIMARY KEY AUTOINCREMENT,
username TEXT UNIQUE NOT NULL,
password TEXT NOT NULL
);
CREATE TABLE post (
id INTEGER PRIMARY KEY AUTOINCREMENT,
author_id INTEGER NOT NULL,
created TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
title TEXT NOT NULL,
body TEXT NOT NULL,
FOREIGN KEY (author_id) REFERENCES user (id)
);
Добавьте функции Python, которые будут выполнять эти SQL-команды, в файл db.py
:
def init_db():
db = get_db()
with current_app.open_resource('schema.sql') as f:
db.executescript(f.read().decode('utf8'))
@click.command('init-db')
def init_db_command():
"""Clear the existing data and create new tables."""
init_db()
click.echo('Initialized the database.')
open_resource()
открывает файл относительно пакета flaskr
, что полезно, поскольку при последующем развертывании приложения вы не всегда будете знать, где находится это место. get_db
возвращает соединение с базой данных, которое используется для выполнения команд, считанных из файла.
click.command()
определяет команду командной строки init-db
, которая вызывает функцию init_db
и показывает пользователю сообщение об успехе. Вы можете прочитать Интерфейс командной строки, чтобы узнать больше о написании команд.
Зарегистрируйтесь в приложении¶
Функции close_db
и init_db_command
должны быть зарегистрированы в экземпляре приложения, иначе они не будут использоваться приложением. Однако, поскольку вы используете фабричную функцию, этот экземпляр недоступен при написании функций. Вместо этого напишите функцию, которая принимает приложение и выполняет регистрацию.
def init_app(app):
app.teardown_appcontext(close_db)
app.cli.add_command(init_db_command)
app.teardown_appcontext()
указывает Flask на вызов этой функции при очистке после возврата ответа.
app.cli.add_command()
добавляет новую команду, которая может быть вызвана с помощью команды flask
.
Импортируйте и вызовите эту функцию из фабрики. Поместите новый код в конец функции фабрики перед возвратом приложения.
def create_app():
app = ...
# existing code omitted
from . import db
db.init_app(app)
return app
Инициализация файла базы данных¶
Теперь, когда init-db
зарегистрирован в приложении, его можно вызвать с помощью команды flask
, аналогично команде run
с предыдущей страницы.
Примечание
Если у вас все еще работает сервер с предыдущей страницы, вы можете либо остановить сервер, либо выполнить эту команду в новом терминале. Если вы используете новый терминал, не забудьте перейти в каталог вашего проекта и активировать env, как описано в Установка.
Выполните команду init-db
:
$ flask --app flaskr init-db
Initialized the database.
Теперь в папке instance
в вашем проекте будет файл flaskr.sqlite
.
Продолжить Чертежи и виды.