Фляжка на примере -Настройка Postgres, SQLAlchemy и Alembic

Оглавление

  • Требования к установке
  • Обновить конфигурацию
  • Модель данных
  • Местная миграция
  • Удаленная миграция
  • Заключение

В этой части мы собираемся настроить базу данных Postgres для хранения результатов подсчета слов, а также  SQLAlchemy, Object Relational Mapper и Alembic для обработки миграции базы данных.


Бесплатный бонус: нажмите здесь, чтобы получить доступ к бесплатному видеоуроку Flask + Python , в котором шаг за шагом показано, как создать веб-приложение Flask.


Обновления:

09.02.2020: Обновлен до версии Python 3.8.1, а также до последних версий Psycopg2, Flask-SQLAlchemy и Flask-Migrate. Подробнее см. Ниже . Явно установите и используйте Flask-Script в связи с изменением внутреннего интерфейса Flask-Migrate.
22.03.2016: Обновлен до версии Python 3.5.1, а также до последних версий Psycopg2, Flask-SQLAlchemy и Flask-Migrate. Подробнее см. Ниже .
22.02.2015: Добавлена ​​поддержка Python 3.


Помните: вот что мы создаем - приложение Flask, которое вычисляет пары частотность слова на основе текста из заданного URL-адреса.


Часть первая : настройте локальную среду разработки, а затем разверните как промежуточную, так и производственную среду на Heroku.Часть вторая: настройте базу данных PostgreSQL вместе с SQLAlchemy и Alembic для обработки миграций. ( текущий )
Часть третья : добавьте внутреннюю логику для очистки, а затем обработки количества слов с веб-страницы с помощью библиотек запросов, BeautifulSoup и Natural Language Toolkit (NLTK).
Часть четвертая : реализация очереди задач Redis для обработки текста.
Часть пятая : настройте Angular во внешнем интерфейсе, чтобы постоянно опрашивать серверную часть, чтобы узнать, обработан ли запрос.
Часть шестая : Отправка на промежуточный сервер на Heroku - настройка Redis и подробное описание того, как запустить два процесса (веб-сайт и рабочий) на одном Dyno.
Часть седьмая : Обновите интерфейс, чтобы сделать его более удобным для пользователя.
Часть восьмая : Создайте настраиваемую директиву Angular для отображения диаграммы частотного распределения с использованием JavaScript и D3.

Требования к установке

Инструменты, используемые в этой части:

PostgreSQL ( 11.6 )
Psycopg2 ( 2.8.4 ) - адаптер Python для Postgres
Flask-SQLAlchemy ( 2.4.1 ) - расширение Flask, обеспечивающее поддержку SQLAlchemy.
Flask-Migrate ( 2.5.2 ) - расширение, которое поддерживает миграцию базы данных SQLAlchemy через Alembic
Для начала установите Postgres на свой локальный компьютер, если у вас его еще нет. Поскольку Heroku использует Postgres, нам будет хорошо разрабатывать локально в той же базе данных. Если у вас не установлен Postgres, Postgres.app - это простой способ начать работу для пользователей Mac OS X. Посетите страницу загрузки для получения дополнительной информации.

После установки и запуска Postgres создайте базу данных, которая wordcount_devбудет использоваться в качестве нашей локальной базы данных для разработки:

$ psql
# create database wordcount_dev;
CREATE DATABASE
# \q

 


Чтобы использовать нашу недавно созданную базу данных в приложении Flask, нам нужно установить несколько вещей:

$ cd flask-by-example

 


cdВход в каталог должен активировать виртуальную среду и установить переменные среды, найденные в .envфайле, с помощью autoenv , который мы установили в части 1 .


$ python -m pip install psycopg2==2.8.4 Flask-SQLAlchemy===2.4.1 Flask-Migrate==2.5.2
$ python -m pip freeze > requirements.txt

 


Если вы используете OS X и у вас возникли проблемы с установкой psycopg2, ознакомьтесь с этой статьей о переполнении стека.

Вам может потребоваться установить psycopg2-binaryвместо, psycopg2если ваша установка не удалась.


Обновить конфигурацию

Добавьте SQLALCHEMY_DATABASE_URIполе к Config()классу в файле config.py, чтобы настроить приложение для использования вновь созданной базы данных при разработке (локальной), промежуточной и производственной:

import os

class Config(object):
    ...
    SQLALCHEMY_DATABASE_URI = os.environ['DATABASE_URL']

 

Ваш файл config.py теперь должен выглядеть так:

import os
basedir = os.path.abspath(os.path.dirname(__file__))


class Config(object):
    DEBUG = False
    TESTING = False
    CSRF_ENABLED = True
    SECRET_KEY = 'this-really-needs-to-be-changed'
    SQLALCHEMY_DATABASE_URI = os.environ['DATABASE_URL']


class ProductionConfig(Config):
    DEBUG = False


class StagingConfig(Config):
    DEVELOPMENT = True
    DEBUG = True


class DevelopmentConfig(Config):
    DEVELOPMENT = True
    DEBUG = True


class TestingConfig(Config):
    TESTING = True

 

Теперь, когда наша конфигурация загружена в наше приложение, к ней также будет подключена соответствующая база данных.

Подобно тому, как мы добавляли переменную среды в предыдущем посте, мы собираемся добавить DATABASE_URLпеременную. Запустите это в терминале:

$ export DATABASE_URL="postgresql:///wordcount_dev"

 

А затем добавьте эту строку в свой файл .env .

В вашем файле app.py импортируйте SQLAlchemy и подключитесь к базе данных:

from flask import Flask
from flask_sqlalchemy import SQLAlchemy
import os


app = Flask(__name__)
app.config.from_object(os.environ['APP_SETTINGS'])
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db = SQLAlchemy(app)

from models import Result


@app.route('/')
def hello():
    return "Hello World!"


@app.route('/<name>')
def hello_name(name):
    return "Hello {}!".format(name)


if __name__ == '__main__':
    app.run()

 

Модель данных

Настройте базовую модель, добавив файл models.py :

from app import db
from sqlalchemy.dialects.postgresql import JSON


class Result(db.Model):
    __tablename__ = 'results'

    id = db.Column(db.Integer, primary_key=True)
    url = db.Column(db.String())
    result_all = db.Column(JSON)
    result_no_stop_words = db.Column(JSON)

    def __init__(self, url, result_all, result_no_stop_words):
        self.url = url
        self.result_all = result_all
        self.result_no_stop_words = result_no_stop_words

    def __repr__(self):
        return '<id {}>'.format(self.id)

 

Здесь мы создали таблицу для хранения результатов подсчета слов.

Сначала мы импортируем соединение с базой данных, которое мы создали в нашем файле app.py, а также JSON из диалектов PostgreSQL SQLAlchemy . Столбцы JSON довольно новы для Postgres и доступны не во всех базах данных, поддерживаемых SQLAlchemy, поэтому нам нужно импортировать их специально.

Затем мы создали Result()класс и присвоили ему имя таблицы results. Затем мы устанавливаем атрибуты, которые хотим сохранить для результата -

  • idрезультата мы сохранили
  • то, urlчто мы посчитали слова из
  • полный список слов, которые мы посчитали
  • список слов, которые мы посчитали за вычетом стоп-слов (подробнее об этом позже)

Затем мы создали __init__()метод, который будет запускаться при первом создании нового результата, и, наконец, __repr__()метод для представления объекта, когда мы его запрашиваем.

Местная миграция

Мы собираемся использовать Alembic , который является частью Flask-Migrate , для управления миграциями базы данных для обновления схемы базы данных.


Примечание. Flask-Migrate использует новый инструмент командной строки Flasks. Однако в этой статье используется интерфейс, предоставляемый Flask-Script , который ранее использовался Flask-Migrate. Чтобы использовать его, вам необходимо установить его через:

$ python -m pip install Flask-Script==2.0.6
$ python -m pip freeze > requirements.txt

 


Создайте новый файл с именем manage.py :

import os
from flask_script import Manager
from flask_migrate import Migrate, MigrateCommand

from app import app, db


app.config.from_object(os.environ['APP_SETTINGS'])

migrate = Migrate(app, db)
manager = Manager(app)

manager.add_command('db', MigrateCommand)


if __name__ == '__main__':
    manager.run()

 

Чтобы использовать Flask-Migrate, мы импортировали Managerтакже Migrateи MigrateCommandв наш файл manage.py . Мы также импортировали, appи dbпоэтому у нас есть доступ к ним из сценария.

Во-первых, мы настраиваем нашу конфигурацию так, чтобы наша среда - на основе переменной среды - создавала экземпляр миграции с аргументами appи dbв качестве аргументов и настраивала managerкоманду для инициализации Managerэкземпляра для нашего приложения. Наконец, мы добавили dbкоманду в managerфайл, чтобы мы могли запускать миграции из командной строки.

Для запуска миграции инициализируйте Alembic:

$ python manage.py db init
  Creating directory /flask-by-example/migrations ... done
  Creating directory /flask-by-example/migrations/versions ... done
  Generating /flask-by-example/migrations/alembic.ini ... done
  Generating /flask-by-example/migrations/env.py ... done
  Generating /flask-by-example/migrations/README ... done
  Generating /flask-by-example/migrations/script.py.mako ... done
  Please edit configuration/connection/logging settings in
  '/flask-by-example/migrations/alembic.ini' before proceeding.

 

После запуска инициализации базы данных вы увидите в проекте новую папку с именем «migrations». Это содержит настройку, необходимую Alembic для выполнения миграций проекта. Вы увидите, что внутри «миграции» есть папка с именем «версии», в которой будут храниться сценарии миграции по мере их создания.

Давайте создадим нашу первую миграцию, выполнив migrateкоманду.

$ python manage.py db migrate
  INFO  [alembic.runtime.migration] Context impl PostgresqlImpl.
  INFO  [alembic.runtime.migration] Will assume transactional DDL.
  INFO  [alembic.autogenerate.compare] Detected added table 'results'
    Generating /flask-by-example/migrations/versions/63dba2060f71_.py
    ... done

 

Теперь вы заметите, что в папке «версии» есть файл миграции. Этот файл автоматически создается Alembic на основе модели. Вы можете самостоятельно сгенерировать (или отредактировать) этот файл; однако в большинстве случаев подойдет автоматически созданный файл.

Теперь мы применим обновления к базе данных с помощью db upgradeкоманды:

$ python manage.py db upgrade
  INFO  [alembic.runtime.migration] Context impl PostgresqlImpl.
  INFO  [alembic.runtime.migration] Will assume transactional DDL.
  INFO  [alembic.runtime.migration] Running upgrade  -> 63dba2060f71, empty message

 

База данных теперь готова для использования в нашем приложении:

$ psql
# \c wordcount_dev
You are now connected to database "wordcount_dev" as user "michaelherman".
# \dt

                List of relations
 Schema |      Name       | Type  |     Owner
--------+-----------------+-------+---------------
 public | alembic_version | table | michaelherman
 public | results         | table | michaelherman
(2 rows)

# \d results
                                     Table "public.results"
        Column        |       Type        |                      Modifiers
----------------------+-------------------+------------------------------------------------------
 id                   | integer           | not null default nextval('results_id_seq'::regclass)
 url                  | character varying |
 result_all           | json              |
 result_no_stop_words | json              |
Indexes:
    "results_pkey" PRIMARY KEY, btree (id)

 

Удаленная миграция

Наконец, давайте применим миграции к базам данных на Heroku. Однако сначала нам нужно добавить сведения о промежуточной и производственной базах данных в файл config.py .

Чтобы проверить, настроена ли у нас база данных на промежуточном сервере, запустите:

$ heroku config --app wordcount-stage
=== wordcount-stage Config Vars
APP_SETTINGS: config.StagingConfig

 


Не забудьте заменить wordcount-stageна имя вашего промежуточного приложения.


Поскольку мы не видим переменную среды базы данных, нам нужно добавить надстройку Postgres на промежуточный сервер. Для этого выполните следующую команду:

$ heroku addons:create heroku-postgresql:hobby-dev --app wordcount-stage
  Creating postgresql-cubic-86416... done, (free)
  Adding postgresql-cubic-86416 to wordcount-stage... done
  Setting DATABASE_URL and restarting wordcount-stage... done, v8
  Database has been created and is available
   ! This database is empty. If upgrading, you can transfer
   ! data from another database with pg:copy
  Use `heroku addons:docs heroku-postgresql` to view documentation.

 


hobby-devэто бесплатный уровень аддона Heroku Postgres.


Теперь, когда мы heroku config --app wordcount-stageснова запустим, мы должны увидеть настройки подключения для базы данных:

=== wordcount-stage Config Vars
APP_SETTINGS: config.StagingConfig
DATABASE_URL: postgres://azrqiefezenfrg::5432/d2kio2ubc804p7

 

Затем нам нужно зафиксировать изменения, которые вы внесли в git, и отправить на промежуточный сервер:

$ git push stage master

 

Запустите миграции, которые мы создали для миграции нашей промежуточной базы данных, используя heroku runкоманду:

$ heroku run python manage.py db upgrade --app wordcount-stage
  Running python manage.py db upgrade on wordcount-stage... up, run.5677
  INFO  [alembic.runtime.migration] Context impl PostgresqlImpl.
  INFO  [alembic.runtime.migration] Will assume transactional DDL.
  INFO  [alembic.runtime.migration] Running upgrade  -> 63dba2060f71, empty message

 


Обратите внимание , как мы только запускали upgrade, не initили migrateкоманды , как и раньше. Наш файл миграции уже настроен и готов к работе; нам просто нужно применить его к базе данных Heroku.


Теперь сделаем то же самое для продакшена.

  1. Настройте базу данных для своего производственного приложения на Heroku, как вы это делали для постановки: heroku addons:create heroku-postgresql:hobby-dev --app wordcount-pro
  2. Отправьте свои изменения на рабочий сайт: git push pro masterобратите внимание, что вам не нужно вносить какие-либо изменения в файл конфигурации - он устанавливает базу данных на основе вновь созданной DATABASE_URLпеременной среды.
  3. Примените миграции: heroku run python manage.py db upgrade --app wordcount-pro

Теперь и на нашем промежуточном, и на производственном сайтах настроены базы данных, они перенесены - и готовы к работе!


Когда вы применяете новую миграцию к производственной базе данных, может возникнуть время простоя. Если это проблема, вы можете настроить репликацию базы данных, добавив «ведомую» базу данных. Подробнее об этом читайте в официальной документации Heroku .


Заключение

Это все, что касается части 2. Если вы хотите глубже изучить Flask, посмотрите нашу сопутствующую серию видео:


Бесплатный бонус: нажмите здесь, чтобы получить доступ к бесплатному видеоуроку Flask + Python , в котором шаг за шагом показано, как создать веб-приложение Flask.


В части 3 мы собираемся создать функцию подсчета слов и отправить ее в очередь задач, чтобы иметь дело с более длительной обработкой подсчета слов.

Увидимся в следующий раз. Ваше здоровье!

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *