Heroku で Flask + SQLAlchemy を使う

Heroku | Cloud Application Platform

Django は動いたので、さて Flask と SQLAlchemy です。

環境

Mac OS X Lion でやっているので、Linux や Windows だとまた別だと思います。

必須

Flask をデプロイする準備

最低限必要なのは virtualenv です。

easy_install なり pip で virtualenv が使える環境は作っておきましょう。

とりあえずプロジェクトフォルダを作成

$ mkdir heroku-flask-sqlalchemy
$ cd heroku-flask-sqlalchemy

virtualenv 環境をフォルダに展開します

$ virtualenv --no-site-packages .
$ source bin/activate

何はともあれ Flask をインストール

$ bin/pip install flask

デプロイ用に gunicorn をインストール

$ bin/pip install gunicorn

heroku は PostgresSQL なので psycopg2 をインストール

$ env ARCHFLAGS="-arch i386 -arch x86_64" bin/pip install psycopg2

ORM として flask-sqlalchemy をインストール

$ bin/pip install flask-sqlalchemy

API 用に simplejson をインストール

$ bin/pip install simplejson

ここでインストールしたサイトパッケージに必要なファイルを書き出します

$ bin/pip freeze > requirements.txt

Flask 用のフォルダを作ります

$ mkdir snowflake

Procfile というファイルを作ります
中身を表示しておきます

$ cat Procfile
web: bin/gunicorn -b 0.0.0.0:$PORT snowflake:app

gunicorn を使ってみました。

snowflake/__init__.py を作って、SQLAlchemy を使ってみます。
ポイントは os.environ.get('DATABASE_URL') です。

import os

import simplejson

from flask import Flask
from flaskext.sqlalchemy import SQLAlchemy

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = os.environ.get('DATABASE_URL')
db = SQLAlchemy(app)

class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    user_name = db.Column(db.String(80), unique=True)
    email = db.Column(db.String(120), unique=True)

    def __init__(self, user_name, email):
        self.user_name = user_name
        self.email = email

    def __repr__(self):
        return '<User %r>' % self.user_name

@app.route('/')
def home():
    return simplejson.dumps([ dict(id = u.id,
                                   user_name = u.user_name,
                                   email = u.email) for u in User.query.all()])

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

Flask をデプロイする

さてここからデプロイ作業です。heroku ではデプロイは git を使います。

まずは不要なファイルがコミットされるのを防ぐため、無視リストを作りましょう。
無視リストは heroku-flask ディレクトリ直下に作ります

$ cat >.gitignore <<EOF
bin/
include/
lib/
*.pyc
EOF

ファイルの確認をしましょう。以下のようなファイルがあるはずです

.git/
.gitignore
Procfile
bin/
include/
lib/
requirements.txt
snowflake/__init__.py

さて次に初期化とファイルの追加です

$ git init
$ git add .
$ git commit -m "Import"

App の作成

$ heroku create --stack cedar
Creating fierce-waterfall-1469... done, stack is cedar
http://fierce-waterfall-1469.herokuapp.com/ | git@heroku.com:fierce-waterfall-1469.git
Git remote heroku added

ここでは fierce-waterfall-1469 と出ていますが、違う表示がされるはずです。それが貴方のアプリ ID です。

heroku create 打つと git に heroku という remote が追加されるはずですので、確認してみて下さい。

$ git remote show heroku
* remote heroku
  Fetch URL: git@heroku.com:fierce-waterfall-1469.git
  Push  URL: git@heroku.com:fierce-waterfall-1469.git
  HEAD branch: (unknown)

remote heroku の URL にアプリケーション名が登録されていれば問題ありません。

push するまえに共有データベース(無償)を追加しておきましょう

$ heroku addons:add shared-database
-----> Adding shared-database to fierce-waterfall-1469... done, v3 (free)

あとは push するだけです。

git push heroku master

これで、デプロイは完了しました。

さてデータベースと言えば初期化ですね。
heroku 側の Python を起動して初期化しましょう。

$ heroku run bin/python
Running bin/python attached to terminal... up, run.6
Python 2.7.1 (r271:86832, Jun 26 2011, 01:08:11) 
[GCC 4.4.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from snowflake import db
>>> db.create_all()

これでデータベースの初期化は終わりました

まずは表示してみましょう

http://あなたのアプリ名.herokuapp.com/

[] が表示されていましたか?

あとはデータを追加してみましょう

$ heroku run bin/python
Running bin/python attached to terminal... up, run.6
Python 2.7.1 (r271:86832, Jun 26 2011, 01:08:11) 
[GCC 4.4.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from snowflake import db
>>> from snowflake import User
>>> admin = User('admin', 'admin@example.com')
>>> guest = User('guest', 'guest@example.com')
>>> db.session.add(admin)
>>> db.session.add(guest)
>>> db.session.commit()

http://あなたのアプリ名.herokuapp.com/

無事 JSON っぽいのが表示されましたか?されていれば成功です。

感想

django の syncdb イイネ。マイクロフレームワークなだけあって、何もしてくれません。
あと自分が Flask 知らなすぎて大変でした ... ちゃんと勉強しないとなぁ。

さんざん悩んだ結果 heroku run bin/python に気付いたので、後は楽でした。heroku のコマンドが色々わからなかったりしているので、迷うことが多々。

ただ、データベースも気軽に使えるので便利ですねほんっと。heroku pg:reset を使うとデータベースを気軽に消したりも出来る様なので、最初の方はこれでいいかもです。ORM つかっておけばローカルは SQLite で作って上は PG でなんても出来たり。

ただ、個人的には管理画面のある Django が便利かなぁなんて思いました。Flask はこったことをやればやるほどしんどくなりそうですし ... 。

気軽に作れるしなれてしまえば色々出来そうなのでオススメですよ。