- en
 - Language: ru
 
- Documentation version: 1.1.x
 
Определение и доступ к базе данных¶
Приложение будет использовать базу данных SQLite для хранения пользователей и постов. Python поставляется со встроенной поддержкой SQLite в модуле sqlite3.
SQLite удобен тем, что не требует установки отдельного сервера баз данных и встроен в Python. Однако, если одновременные запросы пытаются одновременно записывать данные в базу данных, они будут замедляться, поскольку каждая запись происходит последовательно. Небольшие приложения этого не заметят. Когда вы станете большим, вам, возможно, захочется перейти на другую базу данных.
В учебнике нет подробного описания SQL. Если вы не знакомы с ним, в документации по SQLite описано language.
Подключение к базе данных¶
Первое, что необходимо сделать при работе с базой данных SQLite (и большинством других библиотек баз данных Python), - это создать соединение с ней. Любые запросы и операции выполняются с использованием этого соединения, которое закрывается после завершения работы.
В веб-приложениях это соединение обычно привязано к запросу. Оно создается в определенный момент при обработке запроса и закрывается перед отправкой ответа.
flaskr/db.py¶import sqlite3
import click
from flask import current_app, g
from flask.cli import with_appcontext
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, необходимыми для создания пустых таблиц:
flaskr/schema.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:
flaskr/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')
@with_appcontext
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 должны быть зарегистрированы в экземпляре приложения, иначе они не будут использоваться приложением. Однако, поскольку вы используете фабричную функцию, этот экземпляр недоступен при написании функций. Вместо этого напишите функцию, которая принимает приложение и выполняет регистрацию.
flaskr/db.py¶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.
Импортируйте и вызовите эту функцию из фабрики. Поместите новый код в конец функции фабрики перед возвратом приложения.
flaskr/__init__.py¶def create_app():
    app = ...
    # existing code omitted
    from . import db
    db.init_app(app)
    return app
Инициализация файла базы данных¶
Теперь, когда init-db зарегистрирован в приложении, его можно вызвать с помощью команды flask, аналогично команде run с предыдущей страницы.
Примечание
Если у вас все еще работает сервер с предыдущей страницы, вы можете либо остановить сервер, либо выполнить эту команду в новом терминале. Если вы используете новый терминал, не забудьте перейти в каталог вашего проекта и активировать env, как описано в Активируйте окружающую среду. Вам также нужно будет установить FLASK_APP и FLASK_ENV, как показано на предыдущей странице.
Выполните команду init-db:
$ flask init-db
Initialized the database.
Теперь в папке flaskr.sqlite в вашем проекте будет файл instance.
Продолжить Чертежи и виды.