HerokuでDjangoのアプリ作成(Django Tutorial編)

前日の続き。

今日は Djangoチュートリアルを進めてみる。


けどその前に、昨日 Heroku の Getting Started with Django on Heroku が終わった〜と書いたけど、最後の syncdb や shell の部分が抜けてたのでまずは確認しておく。

Heroku のデプロイした環境で syncdb と shell を確認

Getting Started with Django on Heroku の最後、syncdb と shell を確認。


Syncing the database
まずはデータベースを syncdb してみる。

(venv)[paraches@praches.com myHeroku]$ heroku run python manage.py syncdb
Running `python manage.py syncdb` attached to terminal... up, run.4122
…
You just installed Django's auth system, which means you don't have any superusers defined.
Would you like to create one now? (yes/no): yes
Username (leave blank to use 'u7623'): 
Email address: xxxxxxxx@gmail.com
Password: 
Password (again): 
Superuser created successfully.
Installing custom SQL ...
Installing indexes ...
Installed 0 object(s) from 0 fixture(s)
(venv)[paraches@praches.com myHeroku]$ 

途中でユーザ名、メールアドレス、パスワードを聞かれるので答える。
このユーザ名とパスワードは後で Django の Admin ページにアクセスする際に使うので要メモ。


Using the Django shell
次に shell を起動。

(venv)[paraches@praches.com myHeroku]$ heroku run python manage.py shell
Running `python manage.py shell` attached to terminal... up, run.7971
Python 2.7.4 (default, Apr  6 2013, 22:14:13) 
[GCC 4.4.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> from django.contrib.auth.models import User
>>> User.objects.all()
[<User: u7623>]
>>> quit()
(venv)[paraches@praches.com myHeroku]$ 

ちゃんと動いてる!
というわけで、以上で Getting Started with Django on Heroku は終了。

ローカルで python manage.py syncdb してみる

次は Djangoチュートリアルを進めてみる。
使ったのは「django tutorial 1.5」で検索して最初に出て来たページ。(日本語版はないのかな?)

Database setup
プロジェクトを作る所まではやってあるので、データベースの設定から。
と、言っても既に settings.py には設定してあるのでとりあえずローカルで syncdb してみる。

(venv)[paraches@praches.com myHeroku]$ python manage.py syncdb
ImproperlyConfigured: settings.DATABASES is improperly configured. Please supply the ENGINE value. Check settings documentation for more details.
(venv)[paraches@praches.com myHeroku]$ 

エラー出た〜!
Heroku サーバ上では問題なかったのだけど、ローカルでやるとエラーになる。


データベースについての設定が settings.py でされていないってエラーなのだけど、考えてみれば当たり前。
settings.py では Heroku サーバで使う設定を最後に付け加えただけで、そうでない場合のデータベースの設定はされていない。
というわけで普通に DATABASES = に設定するのかな?と思ったけど(web では DATABASES に postgresql を指定している話が多い)、postgresql は使ったことないしユーザ設定とか面倒…。


で、探してみると settings.py の最後に加えた dj_database_url.config() で使うデータベースの設定ができるみたい。
ここで default の値として使用するデータベースの URL を渡せば、Heroku サーバ以外(ローカル)ではその値を使うらしい。

ただ、default='postgres://localhost'ってな感じで postgresql を指定するのがやっぱり多い…。
sqlite じゃダメ? と思ったけど、sqlite を使っている人もいるみたいなのでやってみた。

# Parse database configuration from $DATABASE_URL
import dj_database_url
DATABASES['default'] =  dj_database_url.config(default='sqlite://localhost/sqlite.database')

settings.py をこんな感じにして、syncdb してみる。

(venv)[paraches@praches.com myHeroku]$ python manage.py syncdb
…
You just installed Django's auth system, which means you don't have any superusers defined.
Would you like to create one now? (yes/no): yes
Username (leave blank to use 'paraches'): 
Email address: xxxxxxxx@gmail.com
Password: 
Password (again): 
Superuser created successfully.
Installing custom SQL ...
Installing indexes ...
Installed 0 object(s) from 0 fixture(s)
(venv)[paraches@praches.com myHeroku]$ 

エラー出ずに成功したよ!

Django のモデル作成

Creating models
次はアプリケーションを作成して、そのアプリケーションで使うモデルを作成する。


まずは polls アプリを作成。

(venv)[paraches@praches.com myHeroku]$ python manage.py startapp polls
(venv)[paraches@praches.com myHeroku]$ ls
Procfile  fitsync  manage.py  polls  requirements.txt  sqlite.database  venv
(venv)[paraches@praches.com myHeroku]$ ls polls/
__init__.py  models.py  tests.py  views.py
(venv)[paraches@praches.com myHeroku]$ 

models.py に Poll と Choice を作成。

(venv)[paraches@praches.com myHeroku]$ cat polls/models.py 
from django.db import models

class Poll(models.Model):
    question = models.CharField(max_length=200)
    pub_date = models.DateTimeField('date published')

class Choice(models.Model):
    poll = models.ForeignKey(Poll)
    choice_text = models.CharField(max_length=200)
    votes = models.IntegerField(default=0)

(venv)[paraches@praches.com myHeroku]$ 

Activating models
settings.py に polls アプリを登録。
settings.py の INSTALLED_APPS はこんな感じになる。

INSTALLED_APPS = (
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.sites',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    # Uncomment the next line to enable the admin:
    # 'django.contrib.admin',
    # Uncomment the next line to enable admin documentation:
    # 'django.contrib.admindocs',
    'polls',
)

models.py から作られるテーブルを確認。

(venv)[paraches@praches.com myHeroku]$ python manage.py sql polls
BEGIN;
CREATE TABLE "polls_poll" (
    "id" integer NOT NULL PRIMARY KEY,
    "question" varchar(200) NOT NULL,
    "pub_date" datetime NOT NULL
)
;
CREATE TABLE "polls_choice" (
    "id" integer NOT NULL PRIMARY KEY,
    "poll_id" integer NOT NULL REFERENCES "polls_poll" ("id"),
    "choice_text" varchar(200) NOT NULL,
    "votes" integer NOT NULL
)
;

COMMIT;
(venv)[paraches@praches.com myHeroku]$ 

syncdb してみる。

(venv)[paraches@praches.com myHeroku]$ python manage.py syncdb

問題なし。


ところで、settings.py でデータベース設定を行っていない場合、データベースファイルはどこにできるんだろう?
と、思って見てみたら manage.py と同じ場所にできてた。

(venv)[paraches@praches.com myHeroku]$ ls
Procfile  fitsync  manage.py  polls  requirements.txt  sqlite.database  venv
(venv)[paraches@praches.com myHeroku]$ 

データベースのファイル名は settings.py の最後に付け足した dj_database_url.config に渡した値。
sqlite は postgres や mySQL に比べて自分でユーザ作ったり色々とする必要がないので楽チン。


Playing with the API
shell で遊んでみる。

(venv)[paraches@praches.com myHeroku]$ python manage.py shell
Python 2.7.2 (default, Mar 21 2012, 03:20:49) 
[GCC 4.1.2 20080704 (Red Hat 4.1.2-51)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> from polls.models import Poll, Choice
>>> Poll.objects.all()
[]
>>> from django.utils import timezone
>>> p = Poll(question="What's new?", pub_date=timezone.now())
>>> p.save()
>>> p.id
1
>>> p.question
"What's new?"
>>> p.pub_date
datetime.datetime(2013, 5, 5, 15, 4, 50, 134537, tzinfo=<UTC>)
>>> p.question = "What's up?"
>>> p.save()
>>> Poll.objects.all()
[<Poll: Poll object>]
>>> 

shell で遊ぶ部分はもう少し先があるけど割愛。
というわけで Writing your first Django app, part 1 は終了。

Django の管理サイトを使えるようにする

次は Writing your first Django app, part 2 に進む。

Activate the admin site
まずは settings.py の INSTALLED_APPS で admin のコメントを外す。

INSTALLED_APPS = (
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.sites',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    # Uncomment the next line to enable the admin:
    'django.contrib.admin',
    # Uncomment the next line to enable admin documentation:
    # 'django.contrib.admindocs',
    'polls',
)

次に manage.py syncdb する。

(venv)[paraches@praches.com myHeroku]$ python manage.py syncdb

fitsync/urls.py の admin の部分を Uncomment する。
こんな感じになる。

(venv)[paraches@praches.com myHeroku]$ cat fitsync/urls.py
from django.conf.urls import patterns, include, url

# Uncomment the next two lines to enable the admin:
from django.contrib import admin
admin.autodiscover()

urlpatterns = patterns('',
    # Examples:
    # url(r'^$', 'fitsync.views.home', name='home'),
    # url(r'^fitsync/', include('fitsync.foo.urls')),

    # Uncomment the admin/doc line below to enable admin documentation:
    # url(r'^admin/doc/', include('django.contrib.admindocs.urls')),

    # Uncomment the next line to enable the admin:
    url(r'^admin/', include(admin.site.urls)),
)
(venv)[paraches@praches.com myHeroku]$ 

Django を起動して http://localhost:5000/admin/ にアクセスして確認。

(venv)[paraches@praches.com myHeroku]$ foreman start
00:24:44 web.1  | started with pid 26337
00:24:44 web.1  | 2013-05-06 00:24:44 [26337] [INFO] Starting gunicorn 0.17.4
00:24:44 web.1  | 2013-05-06 00:24:44 [26337] [INFO] Listening at: http://0.0.0.0:5000 (26337)
00:24:44 web.1  | 2013-05-06 00:24:44 [26337] [INFO] Using worker: sync
00:24:44 web.1  | 2013-05-06 00:24:44 [26344] [INFO] Booting worker with pid: 26344


管理者ページは表示されたけど css へのパスが通ってない…。


とりあえず css は置いておいて、次は commit して push してみる。
ここの最後の方に変更の反映方法が書いてあった。

(venv)[paraches@praches.com myHeroku]$ git add .
(venv)[paraches@praches.com myHeroku]$ git commit -m "Add polls application"
(venv)[paraches@praches.com myHeroku]$ git push heroku master

push は問題なく終了。


で、MacSafari から Herokuのサーバにアクセスしてみると、ちゃんと Django 管理サイトのログイン画面が表示された!(けど、もちろん css は読み込めてない…)
サーバの Django 管理サイトへのログインだけど、これは heroku run python manage.py syncdb した時に設定したユーザ名とパスワードを使用する。(上の例では U7623 がユーザ名。)
これもちゃんと Heroku サーバ上でログインできた!


次に管理画面から polls のデータにアクセスしてみたのだけど…エラーになる。

DatabaseError at /admin/polls/poll/add/
relation "polls_poll" does not exist
LINE 1: INSERT INTO "polls_poll" ("question", "pub_date") VALUES ('H...
                    ^
…
Exception Type:	DatabaseError
Exception Value:	
relation "polls_poll" does not exist
…


ただし、これは Heroku 上ではまだ syncdb してなかったというチョンボ
というわけで、heroku run してみた。

(venv)[paraches@praches.com myHeroku]$ heroku run python manage.py syncdb

問題なくできたので、再度トライしたらちゃんと polls のデータにアクセスできました。

Heroku の Django で管理サイトの css を読み込めるようにする

検索して見つけたのが下記のページ。

collectstatic というコマンドで static ファイルを django 起動前に準備するらしい。


結局、自分の場合は Procfile でこんな感じに指定した。(fitsync は Django のプロジェクト名)

(venv)[paraches@praches.com myHeroku]$ cat Procfile
web: python manage.py collectstatic --noinput; gunicorn_django --bind=0.0.0.0:$PORT fitsync/settings.py 

(venv)[paraches@praches.com myHeroku]$ 

そして fitsync/urls.py の最後に以下を加えた。

import settings
urlpatterns += patterns('',
    url(r'^static/(?P<path>.*)$', 'django.views.static.serve', {
        'document_root': settings.STATIC_ROOT,
    }),
)

これでローカルでも Heroku サーバ上でもちゃんと Admin の管理サイトの css が読み込めるようになったよ!

とりあえずのまとめ

今日は Djangoチュートリアルを進めてみた。
VPS で設定するのと違って、Heroku 前提だと色々と違いも多いのであちこちで躓いている。
管理サイトの css の読み込みなどについては、Heroku の Django のページで説明してくれていると良いのだけど…。
ただ、Heroku の Django の static ファイルは Amazon S3 に置くのが常套手段っぽい?ので、そっちを調べてみる必要があるのかも。


次は Djangoチュートリアル 3 には行かずに、今回あれこれ躓いて知った小さなことについてメモしておく予定。