最近、アルバイトでDjango+HerokuでFacebookアプリを作っている。 その過程で、開発しやすい環境を構築するために気づいたことをメモ
はじめに
Herokuの 公式チュートリアル は非常に充実しています。 まずは公式チュートリアルをしっかり読みましょう。 そうすれば、デプロイまではすらすらできるはずです。
データベースの設定
Herokuでは、デプロイ時に勝手に使用するデータベースをHerokuのデータベースに書き換えてくれます。
というわけで、settings.pyには気にせずローカルのデータベースの設定を書きましょう。
一応、HerokuはPostgreSQLを使っているので、 ローカルではPostgreSQL、もしくは設定が簡単なSQLite3を使うのがお勧めです。
環境変数を使おう
やはり、実際に開発を行うとなると、本番環境だけでなく、ローカル環境や、更にステージング環境も必要になります。 また、Fabebookアプリの開発となるとサーバーだけでなくアプリも本番用と開発用を用意する必要が出てきます。
そんな時に、DEBUGモードの切り替えやアプリIDを書き換えをいちいち手動で行なっていたのでは事故のもとですし、 なにより面倒くさい!
というわけで、こんな時に役に立つのがHerokuの環境変数設定機能。 環境ごとに変更が必要な情報をすべて環境変数から受け取ることで、イチイチ書き換える手間を省こうということです。 Herokuでは、
heroku config:add *変数名* = *値*
とすることで環境変数を設定できます。 これは、完全に一般の環境変数と同じなので、
>>> import os >>> os.environ[' *変数名* ']
で参照できます。 これを使って、settings.pyにて、
>>> FACEBOOK_APP_ID = os.environ[' *変数名* ']
などとしておけば、1度環境変数を設定してしまえば、後は自動で書き換えてくれるわけです。 参考: Herokuで認証付きのステージング環境を構築する
foreman を使おう
先ほどの環境変数の設定の話を聞いて、「ローカルでも環境変数設定しないといけないの?」とか、 「それだと、他のアプリの環境変数とかと衝突するんじゃない」とか、思ったかもしれません。 そこで、役に立つのがforemanです。
sudo gem install foreman
でインストールできます。 チュートリアルを読んだ方であれば、途中で出てきたので見覚えがあるかもしれません このforemanの便利な機能として、同じディレクトリに .env ファイルを入れておき、
foreman run *コマンド*
とすれば、そこに書かれた環境変数を設定した上でプログラムを実行してくれます。 .envファイルは単純で
*変数名* = *値*
をどんどん並べていくだけです。たとえば、こんな感じになります。
RACK_ENV='local' FACEBOOK_APP_ID='1234567891234'
これを設定した上で、
foreman run python project/manage.py shell
のように使います。
ここで、少し注意。
コマンドに引数が必要なとき、
foreman run python project/manage.py syncdb --verbosity=2
などとすると--verbosityがforemanの引数として扱われてしまい、うまく動作しません。 なので、
foreman run 'python project/manage.py syncdb --verbosity=2'
のようにしましょう。
パスの設定
>>> TEMPLATE_DIRS = ('/home/user/mysite/templates/', )
のように、絶対パスで指定してしまった場合には、当然、デプロイ後にはHerokuのサーバー上でのパスに書き換える必要が生じます。
ですが、正直、Heroku上でのパスを調べるのは非常に面倒ですし、いちいち書き換えるのも面倒です。
と、言うわけでPython側で動的に生成してもらいましょう。settings.pyに、
>>> import os >>> SITE_ROOT = os.path.realpath(os.path.dirname(__file__)) >>> TEMPLATE_DIRS = (os.path.join(SITE_ROOT, 'templates'), )
のように記述すれば、``SITE_ROOT = os.path.realpath(os.path.dirname(__file__))``の部分で、 Djangoのプロジェクトのルートディレクトリを自動で取得してくれるので、もう書き換える必要はありません。
基本的に、絶対パスが必要な部分については、すべてこのように書くと便利です。
データベースの変更
Djangoは、モデルのスキーマの更新を自動で反映してくれないので、 意外とデータベースを直接操作しなければならない局面も多いです。
Herokuの最大の弱点は、無料プランだと、データベースを直接叩く方法がなく、 Heroku側で作業しようとすると、pythonのシェルを通して、ちまちま調整するしかないです。
ですが、その代わり、Herokuにはデータベースをローカルにコピーする機能と、 ローカルのデータベースをアップロードする方法が提供されています。これを利用します。 ここでは、tapsを用いた方法を紹介します。まずは、tapsをインストールします。
sudo gem install taps
では、データベースを取ってきてみましょう。
heroku db:pull sqlite://local.sqlite3
これで、Herokuのデータベース上のデータがローカルにコピーされます。 これを編集して、Heroku側にアップロードするときは、
heroku db:push sqlite://local.sqlite3
で、できます。当然ながら、元のデータベースは上書きされるので気をつけて下さい。
もっと簡単にデータベースの変更
とはいっても、いちいちデータベースをまるごとコピーしていたのでは、時間がかかりすぎます。
要するにDjangoがHeroku側で勝手にモデルのスキーマを更新してくれれば万事解決するわけです。 なので、その機能を提供するDjangoプラグインの django-evolution を使用します。 導入は超簡単で、
pip install django-evolution
で、インストールし、settings.pyのINSTALLED_APPSに、 django_evolution を追加します。 そして、モデルのスキーマを更新したときは、
heroku run 'python manage.py evolve --hint --execute'
と打ち込むだけで、モデルの更新が完了します。
注釈
Djangoのプラグインでこのような機能を提供するものには、もうひとつSouthというものもあるのですが、 スキーマの生成方法を記述したファイルを一度ローカルに作成しなければならないため、 ファイルの書き込みができないHerokuでは少し使用するのが難しいため、こちらを使用しました。