メモ。
以前、Heroku の Getting Started with Python on Heroku チュートリアルをやった時に
一応、最後まで進めることはできたんだけど、heroku local でローカルでアプリを立ち上げた時 /db にアクセスするとエラーになってしまい、そこだけうまくいってなかった。
/db に対応するビューの処理は
def db(request): greeting = Greeting() greeting.save() greetings = Greeting.objects.all() return render(request, 'db.html', {'greetings': greetings})
なので、Postgres の設定まわりがうまくいってないんだろうとは思いつつ結局原因を突き止められずにいたが、その後ようやくわかったのでメモ。
TL;DR
clone してきたリポジトリの README に書いてある通り、下記のコマンドを実行すればよかった。
(実行には foreman という gem が必要になるので、
なければ gem install foreman でインストールする)
$ createdb python_getting_started $ foreman run python manage.py migrate
前提:Postgres をインストールする
前提として、Postgres が正しくインストールされていることを確認する。
自分は公式ドキュメントに書かれている Postgres.app ではなく、Homebrew から入れてた。
$ brew install postgresql
「Homebrew Postgres」とかでググるとこのへんの記事が見つかるんだけど、
Homebrewを使ったPostgreSQLのインストール(Mac OS Lion) - Qiita
initdb などは brew install した時に自動的に設定されてるらしく不要だった。
ただ、Heroku 公式ドキュメントのここにある通り、DATABASE_URL を設定しておいた方が良い。
https://devcenter.heroku.com/articles/heroku-postgresql#local-setup
使用しているシェルに合わせて設定ファイルに以下を記載する。
(自分の場合は zsh なので .zshrc に記載)
export DATABASE_URL=postgres:///$(whoami)
Postgres.app を入れた場合はどういう設定が必要なのか未確認。
ただ、少なくとも psql などのコマンドへのパスが通ってないので設定する必要がある。
ref. Using Command Line Tools with Postgres.app
export PATH=$PATH:/Applications/Postgres.app/Contents/Versions/9.4/bin
最初のエラー
/db にアクセスした時に最初に表示されたエラーがこれ。

OperationalError at /db
FATAL: database "python_getting_started" does not exist
エラーメッセージの通り、python_getting_started というデータベースが存在しないのが原因。
そのため、
$ createdb python_getting_started
でデータベースを作成してやれば OK。
では、python_getting_started というデータベース名はどこからきたのかというと
リポジトリ内に .env があり、そこに書かれていた。
DATABASE_URL=postgres:///python_getting_started
.env についてはチュートリアルの Define config vars にも出てきたが、
ここに書いた変数は heroku local した時に自動的に読み込まれ、環境変数にセットされる。
次のエラー
無事にデータベースを作成した後発生したのが次のエラー。

ProgrammingError at /db
autocommit cannot be used inside a transaction
これはローカルだけでなくデプロイしたアプリでも最初に発生するエラーで、
テーブルが作られていないのが原因。
ref. https://devcenter.heroku.com/articles/getting-started-with-python#provision-a-database
Accessing it will yield an error though, because while the database is configured, the tables have not been created. Run the standard Django
manage.py migrateto create the tables.
ということでチュートリアルでは
$ heroku run python manage.py migrate
を実行してうまくいったので、ローカルでも同じコマンドを実行する。
$ python manage.py migrate
Operations to perform:
Synchronize unmigrated apps: staticfiles, messages, hello
Apply all migrations: admin, contenttypes, auth, sessions
Synchronizing apps without migrations:
Creating tables...
Creating table hello_greeting
Running deferred SQL...
Installing custom SQL...
Running migrations:
Rendering model states... DONE
Applying contenttypes.0001_initial... OK
Applying auth.0001_initial... OK
Applying admin.0001_initial... OK
Applying contenttypes.0002_remove_content_type_name... OK
Applying auth.0002_alter_permission_name_max_length... OK
Applying auth.0003_alter_user_email_max_length... OK
Applying auth.0004_alter_user_username_opts... OK
Applying auth.0005_alter_user_last_login_null... OK
Applying auth.0006_require_contenttypes_0002... OK
Applying sessions.0001_initial... OK
なんとなく全部うまくいってる感じがしたので再度 /db にアクセスするも、改善していない。
これは、python manage.py migrate だけだと .env で指定している DATABASE_URL を考慮せず、.zshrc で指定した DATABASE_URL が指すデータベースに対してテーブルを作成しているからのよう。
で、それを解決するには foreman という Ruby Gem が必要。
foreman run コマンドについてはちゃんと調べ切れていないが、foreman run に続いて実行したいコマンドを入力すると
.env を考慮した状態でコマンドが実行される。
$ foreman run python manage.py migrate
Operations to perform:
Synchronize unmigrated apps: staticfiles, messages, hello
Apply all migrations: admin, contenttypes, auth, sessions
Synchronizing apps without migrations:
Creating tables...
Creating table hello_greeting
Running deferred SQL...
Installing custom SQL...
Running migrations:
Rendering model states... DONE
Applying contenttypes.0001_initial... OK
Applying auth.0001_initial... OK
Applying admin.0001_initial... OK
Applying contenttypes.0002_remove_content_type_name... OK
Applying auth.0002_alter_permission_name_max_length... OK
Applying auth.0003_alter_user_email_max_length... OK
Applying auth.0004_alter_user_username_opts... OK
Applying auth.0005_alter_user_last_login_null... OK
Applying auth.0006_require_contenttypes_0002... OK
Applying sessions.0001_initial... OK
この状態で /db にアクセスすると正しく動いてるのがわかる。

よかった。
TODO
python manage.py migrateでやっていること
Django の話。たぶんこのへん。
Migrations | Django documentation | Django
- foreman について
heroku local などのコマンドも、内部で実行しているのはこの foreman というコマンドらしい。
Running Apps Locally | Heroku Dev Center
なので、heroku local のかわりに
$ foreman start web
としてもアプリが起動する。
(2015/12/13追記)
こんなエラーも出た。