Cloud9で開発したdjangoプロジェクトをherokuで公開

# Cloud9で開発したdjangoプロジェクトをherokuで公開

## プロローグ

[前回の記事](http://qiita.com/soogie/items/4f0833b9c59cf299fdc6)でherokuを少し使ってみました。
あれから3ヶ月，Rの経験値も上がってきましたが，今回はRではなくPythonを使ったお話です。

Rはパッケージも多く，昨年は書籍もたくさん出ましたし，最近はTokyoRを通じて知りあったRガチ勢の皆様が四六時中参加しているslackもあって，とても便利なのですが，基本的に統計処理を念頭に作られたものということもあり，データの前処理ではawkを使ったりしていました。しかしawkは会社のWindows7(32bit)環境で使うにはいろいろ面倒です。
そこで実は2015年夏くらいから情報収集を始め，Python関連の勉強会にもいろいろ参加してました（あとjuliaも）。

- [みんなのPython勉強会StartPythonClub(#StaPy)](http://startpython.connpass.com/)　
- [Pythonもくもく会@アライドアーキテクツ(#mokupy)](http://mokupy.connpass.com/)
- [Python入門者の集い(#PyNyumon)](http://python-nyumon.connpass.com/) 
- [TokyoDjangoMeetup(#djangoja)](http://django.connpass.com/)
- [Pythonエンジニア養成読本読書会(#pymook)](http://pymook.connpass.com/)
- [Python mini Hack-a-thon(#pyhack)](http://pyhack.connpass.com/)

並べてみるといっぱい参加したみたいですが，複数回参加したのは一番上のStartPythonClubだけで，他のはまだ1回ずつしか参加してません。

そんなPython初心者の私が職場の同僚から「djangoでwebアプリを作りたい」という相談を受けて，

1. Python3で
2. django1.9で
3. Cloud9IDE上でWebアプリを作って
4. SQLite3からPostgreSQLに移行して
5. herokuにデプロイ

までをがんばった，というお話です。

特に3〜5で苦労したので，そのあたりについて重点的にまとめてみたいと思います。

## 準備するもの

- Cloud9のアカウント：ない人は[ここ](https://c9.io/signup)からサインアップ
- herokuのアカウント：ない人は[ここ](https://signup.heroku.com/login)からサインアップ
- Cloud9やherokuにログインできるコンピュータ
- 作りたいアプリの構想

これだけです。
ちなみになんでわざわざCloud9かというと，Pythonに興味を持ち始めた同僚の質問にいろいろ答えるにあたり，同一の環境を用意することができるクラウド上の統合開発環境が一番便利だったからです。

あと，自宅ではMac，会社ではWindows7のため，OSや文字コード，改行コードの違いに振り回されたくない，というのもあります。


## Cloud9でPython3＆djangoのアプリ開発

### djangoワークスペースを作る

Cloud9にログインし，ダッシュボード画面からCreate a new workspaceをクリックします。
![ワークスペースの追加](https://qiita-image-store.s3.amazonaws.com/0/62278/93e3b466-5306-6949-8132-dcfb29108c1a.png)

プロジェクト名（仮にabc）を入力し，下の方のテンプレート一覧からdjangoテンプレートを選択してCreate workspaceボタンをクリックします。
![djangoプロジェクトを選択](https://qiita-image-store.s3.amazonaws.com/0/62278/19c50f4f-6301-a4ba-bf9f-9b4a0b3674ae.png)

djangoテンプレートでワークスペースが作成されました。初期のフォルダ構成はこうなっています。
![初期のフォルダ構成](https://qiita-image-store.s3.amazonaws.com/0/62278/a2b77e7e-d1b8-16ba-81bf-5d2bf801a735.png)
`c9_abc`というのがdjangoのプロジェクトフォルダーです。

### Python3の環境にする

Cloud9のテンプレートではPython2.7とそれに対応したdjangoが構成されます。
私はPython3で開発したいので，Python3で動くように設定を変えましょう。

ワークスペースのメニューからCloud9 - Preferenesでプロジェクト設定画面を開きます。
![Preferences](https://qiita-image-store.s3.amazonaws.com/0/62278/b518ffe9-fd59-a3e7-966e-00d2b8faa187.png)

Language SupportセクションでPython2をPython3に変更します。
![Language Support](https://qiita-image-store.s3.amazonaws.com/0/62278/f1da8bdb-634f-8323-1969-43fb4434299a.png)

ただし，PreferenceをPython3にしても，コマンドラインで `python --version`とするとPython2.7のままです。

    $ python --version
    Python 2.7.6

あとで何度も`python manage.py migrate`などと叩く予定なので `/usr/bin/python`がPython3を指すようにしておきましょう。

    $ sudo mv /usr/bin/python /usr/bin/python2
    $ sudo ln -s /usr/bin/python3 /usr/bin/python
    $ python —version
    python 3.4.3    

方法はこちらの記事を参考にしました。[^1]
こういうことを気兼ねなくできるのもCloud9の便利なところですね。

さて，abcプロジェクトを走らせてみましょう。メニューバーのRun Projectをクリックします。
![Run Project](https://qiita-image-store.s3.amazonaws.com/0/62278/bd9ef218-63b5-84f8-a1f2-a49fe2d6d547.png)

あれ，動きませんね。
![djangoエラー](https://qiita-image-store.s3.amazonaws.com/0/62278/f45b8e63-8e28-b8e0-dcc6-d72b4b1203b2.png)

「djangoがないよ」と言っているようです。Python3にしたせいでdjangoが入っていないのかも。
ということで，djangoをインストールします。Python3なのでpip3を使いましょう。

    $ sudo pip3 install django

改めてRun Projectをクリックすると，今度はちゃんと動きました。
![django動いた](https://qiita-image-store.s3.amazonaws.com/0/62278/7b172115-fb5f-5dc8-fad5-f7777fb419cd.png)

### heroku用のdjango系ファイル一式と置き換える

Cloud9上で開発するだけならこのままでも良いのですが，あとでherokuにデプロイするために，herokuが用意しているdjangoプロジェクトのテンプレートと置き換えておきます。
この辺の手順はこちらの記事 [^2] を参考にしました。

まずワークスペースを作成した時に自動的に構成されたdjangoプロジェクトを削除します。
プロジェクトフォルダーだけでなく，manage.pyなども消してしまいます。
![さっくり削除](https://qiita-image-store.s3.amazonaws.com/0/62278/1b10840d-36d3-645d-7f97-9e966256a04b.png)

次にGitHubからheroku用のdjangoテンプレートを持ってきます。

    $ django-admin.py startproject --template=https://github.com/heroku/heroku-django-template/archive/master.zip --name=Procfile c9_abc

一番最後のc9_abcはさっき消したdjangoプロジェクトフォルダと同じ名前です。

フォルダ構成をみると，ちょっと変ですね。階層がひとつずれています。
![階層がひとつずれている](https://qiita-image-store.s3.amazonaws.com/0/62278/3ae553a1-099a-730c-007f-325c30ab7913.png)

manage.pyが最上層にくるように，1階層ずつ上の階層に移動します。最下層に残ったabc\c9_abc\c9_abcフォルダは空っぽになりますので削除します。
![階層を修正](https://qiita-image-store.s3.amazonaws.com/0/62278/2a6a99b0-4e40-eedb-8bf8-140df5ada8b7.png)

参考にした記事 ではCloud9上で動くようにsettings.pyやwsgi.pyを編集していますが，herokuにデプロイするときにまた戻す必要があり面倒くさいので，必要なライブラリをインストールしてしまいます。

    $ sudo pip3 install dj-database-url
    $ sudo pip3 install Whitenoise
    $ sudo pip3 install Gunicorn

Run Projectで動作確認します。

### アプリ開発＆テスト
今回はアプリの中身は割愛します。

なにせPython初心者なので，django以前にPythonの文法やライブラリの使い方をいちいち調べないと進みません。

Pythonのライブラリの使い方については[Pythonライブラリ厳選レシピ(技術評論社)](http://www.amazon.co.jp/Python-%E3%83%A9%E3%82%A4%E3%83%96%E3%83%A9%E3%83%AA%E5%8E%B3%E9%81%B8%E3%83%AC%E3%82%B7%E3%83%94-%E6%B1%A0%E5%86%85-%E5%AD%9D%E5%95%93/dp/4774177075/ref=sr_1_1?ie=UTF8&qid=1457793060&sr=8-1&keywords=python+%E3%83%A9%E3%82%A4%E3%83%96%E3%83%A9%E3%83%AA)に大変お世話になりました。

djangoについては以下のサイトに特にお世話になりました。

- [djangoproject.jp](http://djangoproject.jp/)
- [django公式ドキュメント](https://docs.djangoproject.com/ja/1.9/) ←一部日本語に翻訳されています。最近本家djangoproject.comにマージされたそうです

すったもんだしながら，何とか動くものができ，職場の同僚に見せて修正，というのを繰り返してひとまず完成しました。
Cloud9だとローカル開発と違って，URLを送るだけでアプリを見せることもできますし，同僚にもCloud9アカウントを持ってもらえば同じワークスペースを共有することも可能です。

余談になりますが，同僚に今回作成したアプリの説明をすることで，私のdjangoについての理解がぐっと進みました。

## SQLite3からPostgreSQLへの移行

さて，せっかく完成したアプリですが，herokuにデプロイする前にもうひとつやっておくことがあります。
デフォルトではdjangoはSQLite3を使っています。そのままherokuにデプロイしてもとりあえずは動きますが，herokuのヘルプにこんな記述があります。

[SQLite on Heroku](https://devcenter.heroku.com/articles/sqlite3)

要するに，「とりあえず動くけど，仕組みの関係で最大24時間で消えちゃうよ」ということのようです。
ちなみにどれくらいで消えちゃうか，試しにやってみましたが1週間くらいたっても消えていないです。たまたまなのか，毎日「消えたかな？」と確認しているせいなのかわかりませんが，本番運用でそんなにドキドキしたくないので，素直にPostgreSQLに移行することにします。
ここではこちらの記事 [^3]とこちらの記事[^4]を参考にしました。

Cloud9のワークスペースにはPostgreSQLがもともとインストールされているので，新たにインストールする必要はありませんが，ステータスを見ると落ちているのでサービスを起動しておきます。

    $ psql --version
    psql (PostgreSQL) 9.3.11
    $ sudo service postgresql status
    9.3/main (port 5432): down
    $ sudo service postgresql start
     * Starting PostgreSQL 9.3 database server
        ...done.

PythonからPostgreSQLを使うためのpsycopg2ライブラリをインストールします。

    $ sudo pip3 install psycopg2
    
次にPostgreSQLにログインします。sudo が2つということにご注意ください。

    $ sudo sudo -u postgres psql
    
PostgreSQLのコンソールでログイン用のユーザー(ここではmyuser)を作ります。    
    
    postgres=# CREATE ROLE myuser LOGIN;
    CREATE ROLE
    postgres=# \password myuser
    Enter new password: 
    Enter it again: 

アプリで使うデータベース(ここではabc)を作成します。Cloud9では最後の`TEMPLATE template0`をつけないと`new encoding (UTF8) is incompatible with the encoding of the template database (SQL_ASCII)`と怒られるのですがどうしたらよいかわからずしばらく悩みました。

    postgres=# CREATE DATABASE abc OWNER myuser ENCODING 'UTF8' TEMPLATE template0;                                                                                
    CREATE DATABASE
    postgres=# \q

これでPostgreSQL側の準備はできました。
続いてdjangoプロジェクト(c9_abc)フォルダのsettings.pyを編集します。

    #DATABASES = {
    #    'default': {
    #        'ENGINE': 'django.db.backends.sqlite3',
    #        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    #    }
    #}   
    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.postgresql_psycopg2', 
            'NAME': 'abc',
                    # The following settings are not used with sqlite3:
                    'USER': ’myuser',
                    'PASSWORD': 'your_password_here',
                    'HOST': '127.0.0.1', 
                    'PORT': 5432, 
                }
    }


最後の手順は少しはまりました。
参考にした記事ではどちらも`python manage.py syncdb`でOKって書いてあるのですが，django1.9のリリースノートに`The syncdb command is removed.`とあり，もはや使えない機能になっています。
調べてみると，[django1.8の公式ドキュメント](https://docs.djangoproject.com/en/1.8/ref/django-admin/#syncdb)に記載があり，`syncdb`は`migrate`のエイリアスで，違いとしてはスーパーユーザーを作るステップが入っていることのようです。ということは，

    $ python manage.py migrate
    $ python manage.py createsuperuser

でOKですね。

これで移行は完了したはずです。念のためアプリがちゃんと動くか確認しておきましょう。

## herokuへのデプロイ

もともとherokuが提供しているテンプレートなので，herokuにPythonのバージョンやインストールするライブラリを指示するファイル(runtime.txtとrequirements.txt)はルートフォルダに作成されています。
しかしherokuもデフォルトでは　Python2.7なので，runtime.txtを修正します。

    [runtime.txt]
    python-3.4.3

次にrequirements.txtも更新します。

    $ pip3 freeze > requirements.txt

ただしこのままでは，Cloud9のPython3の環境に入っているライブラリがすべて盛り込まれてしまいますので，内容を確認して不要なライブラリの行は削除してしまいましょう。
最初にvenvなどで環境を切っていれば，不要なライブラリの行を削除する作業は不要です。ライブラリの依存関係があったりするので，ちゃんとやりたい人は最初に環境を切りましょう。

続いてheroku toolkitをインストールします。

    $ wget -O- https://toolbelt.heroku.com/install-ubuntu.sh | sh

インストールが完了したらさっそくherokuにログインします。

    $ heroku login

アプリ開発の作業でgitリポジトリを作っていなかった人は作成します。

    $ git init
    $ git add -A
    $ git commit -m 'initial commit'

heroku上にアプリのリポジトリを作成します。下の例ではアプリ名として`myherokuapp`とつけています。これをつけなくてもherokuが自動で割り当ててくれますが20文字くらいの長い名前になります。

    $ heroku create myherokuapp

続いていよいよデプロイします。

    $ git push heroku master
    Counting objects: 130, done.
    Delta compression using up to 8 threads.
    Compressing objects: 100% (121/121), done.
    Writing objects: 100% (130/130), 1.91 MiB | 726.00 KiB/s, done.
    Total 130 (delta 52), reused 0 (delta 0)
    remote: Compressing source files... done.
    remote: Building source:
    remote:
    remote: -----> Python app detected
    remote: -----> Installing python-3.4.3
    remote:      $ pip install -r requirements.txt
    remote:        Collecting Django==1.9.4 (from -r requirements.txt (line 1))
    remote:          Downloading Django-1.9.4-py2.py3-none-any.whl (6.6MB)
    (中略)
    remote:        https://myherokuapp.herokuapp.com/ deployed to Heroku
    remote:
    remote: Verifying deploy.... done.
    To https://git.heroku.com/myherokuapp.git
     * [new branch]      master -> master

しばらく待っていると上のような感じでデプロイが完了します。エラーになった人はログやエラーメッセージを確認して，必要な修正をお願いします。

さあもう一息です。heroku上でデータベースの初期化とスーパーユーザーの作成をおこないます。

    $ heroku run python manage.py migrate
    $ heroku run python manage.py createsuperuser

デプロイの途中で表示されたアプリのurl(上の例では`https://myherokuapp.herokuapp.com/`)を開いてみましょう。

問題なく動きましたか？そうしたらdjangoのデバッグモードを切っておきましょう。
Cloud9上でsettings.pyを編集します。

    # DEBUG=True
    DEBUG=False
    
この修正をherokuに反映します。

    $ git add .
    $ git commit -m 'Debug mode off'
    $ git push heroku master

今後も修正したらこの3行（コミットコメントは適宜変えますが）を繰り返し使うことになりますので覚えておきましょう。

以上になります。
勘違いしている点，間違っている点等ありましたらご遠慮なく編集リクエスト等でお知らせください。よろしくお願いします。

----
この記事は@hirokikyさん作の[PileMd](https://pilemd.com)で書きました

# 参考記事

[^1]: Writing a Python App  https://community.c9.io/t/writing-a-python-app/1609
[^2]: How to deploy a Django project in Cloud9 to Heroku http://matthewstibbard.com/2016/01/15/how-to-deploy-a-django-project-in-cloud9-to-heroku/
[^3]: PostgreSQLとDjangoでデータベースを作る https://sites.google.com/site/pcchatnetoiles/home/postgresql/postgresqldjango 
[^4]: djangoでsqlite3からpostgreSQLに移行してみた。 http://freedom-man.com/blog/django_from_sqlite3_to_postgresql/
[^5]: ローカルのDjangoアプリケーションをHerokuにデプロイする手順 http://source.hatenadiary.jp/entry/2013/02/05/173636