dackdive's blog

新米webエンジニアによる技術ブログ。JavaScript(React), Salesforce, Python など

[Python]HerokuでDjangoアプリケーション開発を始めるためのテンプレート

この記事は Heroku Advent Calendar 2015 22 日の記事です。

はじめに

Heroku と言えば Ruby!な印象がどうしても強いですが、Ruby 以外にも様々な言語をサポートしています。
Python もそのひとつです。
ref. Language Support | Heroku Dev Center

Python(Django) に関しては公式のチュートリアルもあるので、とりあえず Heroku にアプリケーションを立ち上げるところまではそこまで苦労せずできます。

※その時のメモはこちら

が、初期設定(特に Postgres)まわりが詳しく書かれておらずつまづくポイントになりそうだというのと、
チュートリアルによって微妙に使っているライブラリやファイルの内容が異なっていたりして
「じゃあ自分で Django アプリケーションを作るにはどこからスタートしたらいいんだろう?」
というのがイマイチわかりませんでした。
なので、今回はそのあたりを簡単にまとめてみます。

先に結論から言ってしまうと、公式ドキュメントの Django and Static Assets | Heroku Dev Center で紹介されているこちらのリポジトリからスタートするのがいいんじゃないかなと思っています。

上記のテンプレートの使い方はおおむね README に書いてある通りなので、既に Python や Heroku に詳しい方は README を読むだけで理解できると思います。
ここでは最初の環境構築と、上記テンプレートの簡単な解説を加えて書きます。


環境構築

前提として、Heroku のアカウント作成や Heroku Toolbelt のインストールは済んでいるとします。
また、使用した私の PC はMac OS X 10.10.5 Yosemite です。

virtualenv, Django のインストール

チュートリアルにも書いてますが、Heroku で Python を扱うには virtualenv を入れると良いです。
Python 自体は pyenv などを入れて自分が使いたいバージョンをインストールするといいと思います。

※ pyenv, virtualenv あたりに詳しくない方はこちらの記事をどうぞ。
[Python]pyenvとvirtualenvとpyenv-virtualenv - dackdive's blog

また、先ほどのリポジトリからテンプレートを clone してくるときに Django のコマンド (django-admin) が必要になるため一緒にインストールします。

# pyenv-virtualenv を使っている場合
$ pyenv install 2.7.10  # 開発に使うバージョン。任意
$ pyenv virtualenv 2.7.10 heroku-py27  # 任意の仮想環境名
$ pyenv global heroku-py27

$ pip install virtualenv
$ pip install django

ここで入れる Django は実際にアプリケーションを稼働させる時には使いません。
が、特に理由がなければバージョンは揃えておいた方がいいんじゃないでしょうか。


Postgres のインストール

Heroku の設計思想でもある The Twelve Factor App の X. Dev/prod parity によれば、開発環境と本番環境はできるだけ一致させるのが望ましいとされています。

Heroku でサポートしている DB はいくつかありますが最もポピュラーなのはおそらく Postgres なので、
別の DB を使う場合を除いてはローカルで動かす時も Postgres を使うようにした方が良いです。

チュートリアルでは Postgres.app をインストールするよう勧められているので今回もそうします。
が、Homebrew でもインストールは可能なようです。

Postgres.app からインストールした場合は CLI を使えるようにパスを通す必要があります。
公式ドキュメント を参考に、.bashrc.zshrc に以下のように書きます。

export PATH=$PATH:/Applications/Postgres.app/Contents/Versions/9.4/bin

※記事執筆時点での Postgres.app のバージョンは 9.4.5 です。実際に設定するときは一度公式ドキュメントから PATH を確認することをオススメします。

(2016/02/12追記)
いつの間にか Postgres.app 9.5 系がリリースされ、PATH の設定も以下のように変更になってました。

export PATH=$PATH:/Applications/Postgres.app/Contents/Versions/latest/bin

これで 9.5 以降はバージョン上がっても PATH を変更する必要がなさそうですね。
ただ、手元の 9.4 系では latest というシンボリックリンクはないようです。
(追記ここまで)

また、ローカルで Heroku アプリを開発するために DATABASE_URL という環境変数も必要になるのでこれも記述します。
ref. https://devcenter.heroku.com/articles/heroku-postgresql#local-setup

export DATABASE_URL=postgres:///$(whoami)


テンプレートの clone

↑で紹介したリポジトリからテンプレートを clone してきます。
このとき、通常の git clone ではなく Djangodjango-admin コマンドを利用して以下のようにします。

$ django-admin.py startproject --template=https://github.com/heroku/heroku-django-template/archive/master.zip --name=Procfile [プロジェクト名]

このコマンドの説明は最後におまけとして載せています。

また、URL 部分が長くて覚えられないので、私は ~/.zshrc に関数として登録しています。

function django-heroku() {
    django-admin.py startproject --template=https://github.com/heroku/heroku-django-template/archive/master.zip --name=Procfile $1
}

データベースの設定がうまくいっているか確認する

clone したリポジトリに移動し、以下のコマンドを実行してエラーにならなければ OK です。

$ python manage.py migrate
...(略)
Operations to perform:
  Apply all migrations: admin, contenttypes, auth, sessions
Running migrations:
  No migrations to apply.


仮想環境を作成する

virtualenv を使って仮想環境を構築し、必要なパッケージをインストールします。

# `venv` というディレクトリは .gitignore に記載されています
$ virtualenv venv

# 仮想環境をアクティベート
$ source venv/bin/activate
(venv) $

# パッケージのインストール。必要なものはすべて requirements.txt に記載済み
(venv) $ pip install -r requirements.txt


ローカルで起動する

$ heroku local web

でローカルサーバーを立ち上げます。
http://localhost:5000/ にアクセスして画面が表示されれば OK です。

f:id:dackdive:20151222104333p:plain

もしうまく起動しない場合はこちらの記事も参考にしてみてください。
[Heroku][Django]Postgres.appで `'django_postgrespool' isn't an available database backend.` エラー - dackdive's blog

基本、heroku local web でうまく起動しなかった時は python manage.py runserver で起動した方が詳細なエラーが得られます。

Heroku にデプロイ

ここはチュートリアルを読めばわかる話でもあるのでさらっと流します。 README にも書いてるようにコミットして heroku に push、で基本的には OK です。

$ git init
$ git add -A
$ git commit -m "Initial commit"

$ heroku create
$ git push heroku master

$ heroku run python manage.py migrate


おわりに

というわけで、「Python/Django は知ってるけど Heroku は初めて」という方に向けて
最初にハマってしまいそうな(というか自分自身がよくわからずハマってしまった)環境構築部分の説明と、便利なテンプレートを紹介しました。

この後は普通の Django アプリケーション開発と同じように進めていけばいいはずです。



おまけ

ここから下は自分で調べたことのメモ書きとして。

テンプレートの clone について

リポジトリからテンプレートを clone するときの以下のコマンドについてです。

$ django-admin.py startproject --template=https://github.com/heroku/heroku-django-template/archive/master.zip --name=Procfile [プロジェクト名]

django-admin.py startproject に2つのオプション templatename を指定しています。

startproject または startapp コマンドには --template=PATH を指定することが可能で、指定した PATH のディレクトリからファイルをコピーして新規プロジェクトを作成できます。
PATH には .zip など圧縮したファイルも指定可能です。また、圧縮ファイルであればローカルのディレクトリだけでなく http, https, ftp などの URL で指定することも可能です。
(ref. https://docs.djangoproject.com/en/1.8/ref/django-admin/#django-admin-option---template)

また、startproject する際にファイル内のテンプレート変数({{ variable }})を置換することができます。
(ref. https://docs.djangoproject.com/en/1.8/ref/django-admin/#startproject-projectname-destination )

上記ドキュメントから引用すると

When Django copies the project template files, it also renders certain files through the template engine: the files whose extensions match the --extension option (py by default) and the files whose names are passed with the --name option. The template context used is:
 

  • Any option passed to the startproject command (among the command’s supported options)
  • project_name – the project name as passed to the command
  • project_directory – the full path of the newly created project
  • secret_key – a random key for the SECRET_KEY setting
  • docs_version – the version of the documentation: 'dev' or '1.x'

一番上の Any option passed ... はよくわかりませんが、

  1. --extension オプションで指定した拡張子のファイル(デフォルトは py
  2. --name オプションで指定したファイル

内に存在する project_name, project_directory などの変数が自動的に置換されるようです。


Django で静的リソースを扱う

デフォルトでは Django は画像やCSSなどの静的リソースを扱うことができません。
正確には、django.contrib.staticfiles というミドルウェアINSTALLED_APPS に指定することで開発中は静的リソースを扱えるようになりますが
DEBUG=True のときのみ、という制約があるため本番環境では別の手段を取る必要があります。
ref. Managing static files (e.g. images, JavaScript, CSS) | Django documentation | Django

今回のテンプレートでは Whitenoise というライブラリを利用しています。

settings.py および wsgi.py を見ると以下のようになっています。

settings.py

# Simplified static file serving.
# https://warehouse.python.org/project/whitenoise/
STATICFILES_STORAGE = 'whitenoise.django.GzipManifestStaticFilesStorage'

wsgi.py

from django.core.wsgi import get_wsgi_application
from whitenoise.django import DjangoWhiteNoise

application = get_wsgi_application()
application = DjangoWhiteNoise(application)

なお、Getting Started with Django on Heroku だと dj-static というライブラリを使っています。
wsgi.py で DjangoWhiteNoise のかわりに Cling とかってやってるやつ)

これについては正直違いがわかりませんが、dj-static は Python3 に対応していないといったブログ記事 が見つかったりしたので
特に問題にならない限りは WhiteNoise を使っていこうと思います。

余談ですが、Djangoミドルウェアである django.contrib.staticfilescollectstatic コマンドを使うために必要だそうです。


さらにおまけ:Djangopy.test を使えるようにするにはこちらのパッケージを入れるとよさそう。
http://pytest-django.readthedocs.org/en/latest/tutorial.html