概要
Flaskに入門したのでherokuデプロイまでの手順を記して置こうと思います。
フェーズ1: Hello, World!アプリ
フェーズ2: sqliteを用いたflaskアプリ
フェーズ3: postgres + herokuにデプロイ
の順番でやっていこうと思います。
環境
- macOS High Sierra 10.13.6
- python 3.6.5
最終的なディレクトリ構成
最終的なディレクトリ構成はこのようになります。
flask-demo-app/
├── run.py
├── app
│ ├── __init__.py
│ ├── config.py
│ ├── views.py
│ ├── models.py
│ ├── test.db
│ └── templates/
├── Procfile
├── requirements.txt
└── venv/
プロジェクトの作成
mkdir flask-demo-app
cd flask-demo-app
git init
python 仮想環境 構築
python3 -m venv venv
source venv/bin/activate
venvに関してはこちらがわかりやすいです。
https://qiita.com/fiftystorm36/items/b2fd47cf32c7694adc2e
source venv/bin/activate
するとこんな感じになっているはずです。
(venv)$
venv環境はgitで管理する必要はないので、
.gitignoreにvenv
を追加しておきます。
venv
flaskのインストール
pipをアップグレードしてflaskをインストールします。
(venv)$ pip install --upgrade pip
(venv)$ pip install flask
フォルダの作成
(venv)$ mkdir main
今回は、このmainディレクトリにflaskの主要ファイルたちを置いていきます。
フェーズ1
まずは最小構成でHello, World!
をしていきます。
run.py
アプリケーションをデバッグモードで起動するだけのプログラムです。
(venv)$ vim run.py
from main import app
if __name__ == '__main__':
app.run(debug=True)
main/_init_.py
(venv)$ vim main/__init__.py
from flask import Flask
app = Flask(__name__)
import main.views
main package
がimportされた際にこのスクリプトが実行されます。
_init_.pyの働きに関してはこちらがわかりやすかったです。
https://www.kangetsu121.work/entry/2018/09/16/004008
main/views.py
(venv)$ vim main/views.py
import flask
from main import app
@app.route('/')
def show_entries():
return 'Hello, World!'
実行
(venv)$ python run.py
http://localhost:5000 へアクセス
Hello, World!
が見えたらOK!
フェーズ2
sqliteデータベースを使用するアプリケーションにしてみます。
Entryというクラスを作成し、ブログ(title, text)を投稿できるようにしていきます。
flask_sqlalchemyのインストール
SQLAlchemyというORMを使用します。
flask用のものをインストール。
(venv)$ pip install flask_sqlalchemy
main/_init_.py を編集
(venv)$ vim main/__init__.py
from flask import Flask
from flask_sqlalchemy import SQLAlchemy # 追加
app = Flask(__name__)
app.config.from_object('main.config') # 追加
db = SQLAlchemy(app) # 追加
import main.views
main/config.py
(venv)$ vim main/config.py
import os
SQLALCHEMY_DATABASE_URI = os.environ.get('DATABASE_URL') or "sqlite:///test.db"
SQLALCHEMY_TRACK_MODIFICATIONS = True
SECRET_KEY="secret key"
or 演算子を使用して、os.environ.get('DATABASE_URL')が空文字だった場合,右辺を代入するようにしています。
os.environ.get('DATABASE_URL')
はherokuのpostgresで使用し、
右辺はsqliteのデータベースです。
こうすることでherokuの環境とローカルの環境で書き換える必要がありません。
SECRET_KEY
はセッション情報を暗号化するためのキーです
実際に運用する場合には、SECRET_KEYは必ず変更してください。
main/models.py
from main import db
from flask_sqlalchemy import SQLAlchemy
class Entry(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.Text)
text = db.Column(db.Text)
def __repr__(self):
return "<Entry id={} title={!r}>".format(self.id, self.title)
def init():
db.create_all()
データベース作成
(venv)$ python -c "import main.models; main.models.init()"
SQLALCHEMY_DATABASE_URI の場所に作成されます。
main/test.db
が存在することを確認してください。
データ挿入
初期データをいくつかいれておきます。
インタラクティブシェルから挿入することができます。
(venv)$ python
>>> from main.models import Entry
>>> from main import db
>>> entry1 = Entry(title='title1', text='text1')
>>> db.session.add(entry1)
>>> db.session.commit()
>>>
>>> entry2 = Entry(title='title2', text='text2')
>>> db.session.add(entry2)
>>> db.sesion.commit()
>>> db.session.commit()
>>> entries = Entry.query.all()
>>> entries
[<Entry id=1 title='title1'>, <Entry id=2 title='title2'>]
>>> exit()
2つのデータを挿入しました。
main/views.py を編集
import flask
from main import app
from main.models import Entry # 追加
@app.route('/')
def show_entries():
entries = Entry.query.all() # 追加
return flask.render_template('entries.html', entries=entries) # 変更
flask.render_template
でhtmlテンプレートが使用できます。
htmlテンプレートはtemplates
に置きます。
htmlテンプレートの準備
(venv)$ mkdir main/templates
(venv)$ vim main/templates/entries.html
<!DOCTYPE html>
<html>
<head>
<title>flask demo app</title>
</head>
<body>
<ul class="entries">
{% for entry in entries %}
<li>{{entry.title}} / {{entry.text}}</li>
{% endfor %}
</ul>
</body>
</html>
実行
(venv)$ python run.py
http://localhost:5000 へアクセス
インタラクティブシェルで挿入したデータが見れたらOK!
フォームの追加
データが表示出来たので、htmlにフォームを設置し、
そこからDBへ追加できるようにします。
views.py の編集
(venv)$ vim main/views.py
import flask
from main import app, db # 変更
from main.models import Entry
@app.route('/')
def show_entries():
entries = Entry.query.all()
return flask.render_template('entries.html', entries=entries)
# add_entry 関数の追加
@app.route('/add', methods=['POST'])
def add_entry():
entry = Entry(
title = flask.request.form['title'],
text = flask.request.form['text']
)
db.session.add(entry)
db.session.commit()
return flask.redirect(flask.url_for('show_entries'))
htmlテンプレート の編集
(venv)$ vim main/templates/entries.html
<!DOCTYPE html>
<html>
<head>
<title>flask demo app</title>
</head>
<body>
<!-- 追加 -->
<form action="{{ url_for('add_entry') }}" method=post>
<input type="text" name="title">
<input type="text" name="text">
<input type="submit">
</form>
<!-- ここまで -->
<ul class="entries">
{% for entry in entries %}
<li>{{entry.title}} / {{entry.text}}</li>
{% endfor %}
</ul>
</body>
</html>
実行
(venv)$ python run.py
http://localhost:5000 へアクセス
postしたデータがviewとしてみれたらOK!
フェーズ3
ここからはherokuへデプロイのための準備をしていく。
heroku用準備
gunicorn のインストール
(venv)$ pip install gunicorn
psycopg2 のインストール
python
からPostgreSQL
を使用するためにドライバのpsycopg2
をインストールします。
(venv)$ pip install psycopg2-binary
pip install psycopg2
を実行するとうまくいかなかったため、
こちらを実行しています。
Procfile の準備
heroku 上で実行するコマンドを記載します。
(venv)$ vim Procfile
web: gunicorn run:app --log-file -
requirements.txt の準備
pip freeze
でインストール済パッケージ一覧を表示することが出来ます。
heroku
はrequirements.txt
を頼りに必要なライブラリをインストールするので準備してあげます。
(venv)$ pip freeze > requirements.txt
herokuアプリの作成
ログイン
(venv)$ heroku login
アプリの作成
(venv)$ heroku create flask-demo-app
こういうエラーが出たら名前がすでに使われているので、
違う名前でアプリを作成してください。
Creating ⬢ flask-demo-app... !
▸ Name flask-demo-app is already taken
postgresql アドオンの追加
(venv)$ heroku addons:create heroku-postgresql:hobby-dev
heroku コミット
まずはgitにコミットして
(venv)$ git add .
(venv)$ git commit
herokuにpush!
(venv)$ git push heroku master
heroku にデータベース作成
(venv)$ heroku run python -c "import main.models; main.models.init()"
(venv)$ heroku open
heroku で確認できたらOKです!
python 仮想環境を抜けるには下のコマンドです。
(venv)$ deactivate
終わりに
heroku デプロイまで出来ましたでしょうか..?
flaskですが、ディレクトリ構成がかなり自由で、どういうファイル配置にしていくか悩みましたが、一旦これに落ち着きました。
なにか間違っているところやこうしたほうがいい!というところがあれば教えてくださると幸いです。