このパートでは、ワードカウントの結果を保存するPostgresデータベースと、データベースの移行を処理するSQLAlchemy、オブジェクトリレーショナルマッパー、およびAlembicをセットアップします。
更新:
- 2020年2月9日:Pythonバージョン3.8.1と、最新バージョンのPsycopg2、Flask-SQLAlchemy、Flask-Migrateにアップグレードしました。詳細については、以下を参照してください。 Flask-Migrate内部インターフェースの変更により、Flask-Scriptを明示的にインストールして使用します。
- 2016年3月22日:Pythonバージョン3.5.1にアップグレードされ、最新バージョンのPsycopg2、Flask-SQLAlchemy、Flask-Migrateにアップグレードされました。詳細については、以下をご覧ください。
- 2015年2月22日:Python3のサポートが追加されました。
注意:これが私たちが構築しているものです-指定されたURLからのテキストに基づいて単語と頻度のペアを計算するFlaskアプリ。
- パート1:ローカル開発環境をセットアップしてから、ステージング環境と本番環境の両方をHerokuにデプロイします。
- パート2:移行を処理するためにSQLAlchemyおよびAlembicとともにPostgreSQLデータベースをセットアップします。 (現在 )
- パート3:バックエンドロジックを追加して、リクエスト、BeautifulSoup、Natural Language Toolkit(NLTK)ライブラリを使用してウェブページから単語数を取得して処理します。
- パート4:テキスト処理を処理するためのRedisタスクキューを実装します。
- パート5:フロントエンドにAngularを設定して、バックエンドを継続的にポーリングし、リクエストの処理が完了したかどうかを確認します。
- パート6:Herokuのステージングサーバーにプッシュします-Redisをセットアップし、1つのDynoで2つのプロセス(Webとワーカー)を実行する方法を詳しく説明します。
- パート7:フロントエンドを更新してユーザーフレンドリーにします。
- パート8:JavaScriptとD3を使用して度数分布図を表示するカスタムAngularディレクティブを作成します。
<マーク>コードが必要ですか?リポジトリから取得します。
インストール要件
このパートで使用されるツール:
- PostgreSQL(11.6)
- Psycopg2(2.8.4)-Postgres用のPythonアダプター
- Flask-SQLAlchemy(2.4.1)-SQLAlchemyサポートを提供するFlask拡張機能
- Flask-Migrate(2.5.2)-Alembicを介したSQLAlchemyデータベースの移行をサポートする拡張機能
開始するには、Postgresをローカルコンピュータにインストールします(まだインストールしていない場合)。 HerokuはPostgresを使用しているため、同じデータベースでローカルに開発することをお勧めします。 Postgresがインストールされていない場合、Postgres.appはMacOSXユーザーが簡単に起動して実行できる方法です。詳細については、ダウンロードページを参照してください。
Postgresをインストールして実行したら、wordcount_dev
というデータベースを作成します。 ローカル開発データベースとして使用するには:
$ psql
# create database wordcount_dev;
CREATE DATABASE
# \q
Flaskアプリ内で新しく作成したデータベースを使用するには、いくつかのものをインストールする必要があります。
$ cd flask-by-example
cd
ディレクトリにアクセスすると、仮想環境がアクティブになり、.env
にある環境変数が設定されます。 パート1で設定したautoenv経由のファイル。
$ 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のインストールに問題がある場合は、このStackOverflowの記事をご覧ください。
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で作成したデータベース接続をインポートします。 ファイルとSQLAlchemyのPostgreSQL方言からのJSON。 JSON列はPostgresにとってかなり新しいものであり、SQLAlchemyでサポートされているすべてのデータベースで使用できるわけではないため、具体的にインポートする必要があります。
次に、Result()
を作成しました クラスにresults
のテーブル名を割り当てました 。次に、結果のために保存する属性を設定します-
-
id
保存した結果の -
url
からの単語を数えた - カウントした単語の完全なリスト
- カウントした単語のリストからストップワードを差し引いたもの(これについては後で詳しく説明します)
次に、__init__()
を作成しました 新しい結果を最初に作成するときに実行され、最後に__repr__()
が実行されるメソッド オブジェクトを照会するときにオブジェクトを表すメソッド。
ローカル移行
Flask-Migrateの一部であるAlembicを使用して、データベースの移行を管理し、データベースのスキーマを更新します。
注: Flask-MigrateはFlasksの新しいCLIツールを利用します。ただし、この記事では、Flask-Migrateが以前使用していたFlask-Scriptが提供するインターフェイスを使用しています。使用するには、次の方法でインストールする必要があります。
$ 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がプロジェクトに対して移行を実行するために必要なセットアップを保持します。 「migrations」の中には、「versions」というフォルダがあり、作成時に移行スクリプトが含まれていることがわかります。
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
HerokuPostgresアドオンの無料利用枠です。
ここで、heroku config --app wordcount-stage
を実行すると ここでも、データベースの接続設定が表示されます。
=== wordcount-stage Config Vars
APP_SETTINGS: config.StagingConfig
DATABASE_URL: postgres://azrqiefezenfrg:Zti5fjSyeyFgoc-U-yXnPrXHQv@ec2-54-225-151-64.compute-1.amazonaws.com: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データベースに対して適用する必要があります。
生産についても同じことをしましょう。
- ステージングの場合と同じように、Herokuで本番アプリのデータベースを設定します。
heroku addons:create heroku-postgresql:hobby-dev --app wordcount-pro
- 本番サイトに変更をプッシュします:
git push pro master
構成ファイルに変更を加える必要がないことに注意してください。これは、新しく作成されたDATABASE_URL
に基づいてデータベースを設定します。 環境変数。 - 移行を適用します:
heroku run python manage.py db upgrade --app wordcount-pro
これで、ステージングサイトと本番サイトの両方でデータベースがセットアップされ、移行され、準備が整いました。
本番データベースに新しい移行を適用すると、ダウンタイムが発生する可能性があります。これが問題になる場合は、「フォロワー」(一般にスレーブと呼ばれる)データベースを追加することでデータベースレプリケーションを設定できます。詳細については、Herokuの公式ドキュメントをご覧ください。
結論
パート2は以上です。Flaskをさらに深く掘り下げたい場合は、付属のビデオシリーズをご覧ください:
パート3では、単語カウント機能を構築し、それをタスクキューに送信して、長時間実行される単語カウント処理を処理します。
またね。乾杯!
これは、StartupEdmontonの共同創設者であるCamLinkeとRealPythonの人々とのコラボレーション作品です。