sgykfjsm.github.com

DjangoをTango with Djangoで学ぶ - 1 -

仕事でDjangoアプリケーションを扱うことになったのでDjangoについて勉強を始めた。参考書としてTango With Djangoを購入した。古いバージョンなら無料で入手できるっぽいけど大して高価な本というわけでもないし購入したほうが良いかなと思って買った。

さて、最初は環境の準備を行い、それからViewの基本とURLマッピングについての学習だ。

準備

これはTango With Djangoに書いてあるやり方ではなくて、いつも自分がPython環境を構築するときのやり方だ。要はDjangoを指定のPythonバージョンで動かせばよいわけだから、いつものやり方で良い。

必要なもの

pyenvpyenv-virtualenvがinstallされていること。

手順

pyenvにバージョン3.5.3をインストールする。

1
2
3
4
5
$ pyenv install 3.5.3
Downloading Python-3.5.3.tar.xz...
-> https://www.python.org/ftp/python/3.5.3/Python-3.5.3.tar.xz
Installing Python-3.5.3...
Installed Python-3.5.3 to /Users/sgyk/.pyenv/versions/3.5.3

作業用Pythonの設定をする。

1
2
3
4
5
6
$ eval "$(pyenv init -)"
$ eval "$(pyenv virtualenv-init -)"
$ pyenv virtualenv 3.5.3 tango-with-django-env
$ pyenv activate tango-with-django-env
$ python --version
Python 3.5.3

Djangoをinstallしてプロジェクトを作る

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
$ pip install django
# Confirm django is installed as expected
$ python
Python 3.5.3 (default, Sep  4 2017, 22:33:15)
[GCC 4.2.1 Compatible Apple LLVM 8.1.0 (clang-802.0.42)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import django
>>> django.get_version()
'1.11.4'
>>> exit()
# $ cd ${YOUR_WORKSPACE}
$ cd tango_with_django_project
$ django-admin.py startproject tango_with_django_project
$ cd tango_with_django_project/
$ ls -l
total 4
drwxr-xr-x 4 sgyk 136  9  4 22:40 ./
drwxr-xr-x 9 sgyk 306  9  4 22:40 ../
-rwxr-xr-x 1 sgyk 823  9  4 22:40 manage.py*
drwxr-xr-x 6 sgyk 204  9  4 22:40 tango_with_django_project/   # <- project configuration directrory

ここまでで準備は完了。とりあえず起動してみる

1
2
3
4
5
6
7
8
9
$ python manage.py runserver
Performing system checks...

System check identified no issues (0 silenced).

You have 13 unapplied migration(s). Your project may not work properly until you apply the migrations for app(s): admin, auth, contenttypes, sessions.
Run 'python manage.py migrate' to apply them.

....

warningが出ているが、これはDBを使うようになるまで放置で良い。http://127.0.0.1:8000/ にアクセスして”It worked!“が表示されることを確認すること。

アプリケーションの準備

ここまではプロジェクトの準備。ここからはアプリケーションの準備を始める。今回はテキストに則ってrangoというアプリケーションを作成する。アプリケーションの準備は以下の通りにコマンドを叩けば良い。

1
$ python manage.py startapp rango

startappコマンドはプロジェクトディレクトリのルートに新しいディレクトリを作成する。

1
2
3
4
5
6
7
8
$ ls -l
total 16
drwxr-xr-x 6 sgyk   204  9  4 22:58 ./
drwxr-xr-x 9 sgyk   306  9  4 22:40 ../
-rw-r--r-- 1 sgyk 12288  9  4 22:52 db.sqlite3
-rwxr-xr-x 1 sgyk   823  9  4 22:40 manage.py*
drwxr-xr-x 9 sgyk   306  9  4 22:58 rango/
drwxr-xr-x 7 sgyk   238  9  4 22:52 tango_with_django_project/

db.sqlite3rangoディレクトリが作成されたことが確認できる。rangoディレクトリの中身は以下の通り。

1
2
3
4
5
6
7
8
9
10
11
$ ls -l ./rango/
total 20
drwxr-xr-x 9 sgyk 306  9  4 22:58 ./
drwxr-xr-x 6 sgyk 204  9  4 22:58 ../
-rw-r--r-- 1 sgyk   0  9  4 22:58 __init__.py
-rw-r--r-- 1 sgyk  63  9  4 22:58 admin.py
-rw-r--r-- 1 sgyk  85  9  4 22:58 apps.py
drwxr-xr-x 3 sgyk 102  9  4 22:58 migrations/
-rw-r--r-- 1 sgyk  57  9  4 22:58 models.py
-rw-r--r-- 1 sgyk  60  9  4 22:58 tests.py
-rw-r--r-- 1 sgyk  63  9  4 22:58 views.py

Djangoの開発では主にviews.pymodels.pyを扱う。Djangoのmodel, viewsそしてtemplatesがどのように関連しているかは https://docs.djangoproject.com/en/1.11/intro/overview/ を参照すると良い。

なお、このあたりでgit initしておくと良い。

最後の準備

これでアプリケーションの準備ができたので開発を始めることができると思いきや、まだしなければならないことがある。それは、Djangoにこれから開発するアプリケーションについて教えてあげないといけない。具体的にはtango_with_django_project/settings.pyにこれから追加するアプリケーションの情報を追加しなければならない。

1
2
3
4
5
6
7
8
9
10
11
12
13
$ git diff
diff --git a/tango_with_django_project/settings.py b/tango_with_django_project/settings.py
index 63c1c9a..8d38aa9 100644
--- a/tango_with_django_project/settings.py
+++ b/tango_with_django_project/settings.py
@@ -37,6 +37,7 @@ INSTALLED_APPS = [
     'django.contrib.sessions',
     'django.contrib.messages',
     'django.contrib.staticfiles',
+    'rango',
 ]

 MIDDLEWARE = [

上記を追加したらpython manage.py runserverを実行し、先ほどと同じようにサーバーが起動することを確認する。

Viewの開発の1歩目

Viewの開発を始める。まずは既存のviews.pyを以下の様に書き換えてみる。

1
2
3
4
5
6
7
8
9
10
11
12
13
$ git diff
diff --git a/rango/views.py b/rango/views.py
index 91ea44a..117afb3 100644
--- a/rango/views.py
+++ b/rango/views.py
@@ -1,3 +1,5 @@
-from django.shortcuts import render
+from django.http import HttpResponse

-# Create your views here.
+
+def index(request):
+    return HttpResponse("Rango says hey there partner!")

ここからわかることは、Viewの仕事は基本的にHttpResponseを返すことだ。

indexが受け取っているrequestとは簡単に言うとRequestオブジェクトである。この中に様々なリクエスト情報が含まれているが、ここでは使っていない。そのため、引数requestを削除しても良いかと思うかもしれないが、これは残しておかないと次に設定するURLのマッピング処理に失敗するので、残しておくこと。

すでに触れたが、上記のviews.pyの修正だけでは、indexの処理にアクセスすることはできない。なぜならば、Djangoにindexへのアクセスするルートを教えていないからだ。このURLマッピング処理は以下の通りに行えば良い。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$ git diff tango_with_django_project/urls.py
diff --git a/tango_with_django_project/urls.py b/tango_with_django_project/urls.py
index af5caa3..c385489 100644
--- a/tango_with_django_project/urls.py
+++ b/tango_with_django_project/urls.py
@@ -15,7 +15,9 @@ Including another URLconf
 """
 from django.conf.urls import url
 from django.contrib import admin
+from rango import views

 urlpatterns = [
+    url(r'^$', views.index, name='index'),
     url(r'^admin/', admin.site.urls),
 ]

url(r'^$', views.index, name='index')が意味するのは、URLのルートにアクセスしたら(r'^$'), views.indexにリクエスト情報を渡して処理をさせる、この処理の名前をindexとする(name='index')、ということだ。name='index'は一見すると無意味な設定に見えるかもしれないが、DjangoのWarningに使われたりするので、いざという時に重要な情報となる。また、DjangoのReverse URL Matchingにも利用される。よって、設定しておくのが良い。

URLのマッピングに関するテクニック

上述したようにURLを一つずつ設定していくことによって、URLとViewを対応付けることができる。しかし、設定したファイルはtango_with_django_projectというプロジェクトの全体設定ファイルである。今は良いが、今後開発が進んでチームで開発するようになることを考えると、いつまでも全体設定ファイルを扱うことはあまり好ましくない。なぜならば、変更の衝突などが発生しうるからだ。これを避けるためには、以下の様にアプローチすれば良い。

  1. 全体設定ファイルにはアプリケーションのURLのプレフィックスを設定する。
  2. 設定したプレフィックスに該当するURLが参照するURLマッピング設定ファイルをアプリケーションのディレクトリ以下に配置する。

これにより、アプリケーションとURLマッピング設定ファイルを1:1対応させることができ、アプリケーション開発者は他のアプリケーション設定に関して気にしなくて良くなる。具体的には以下の様に設定すれば良い。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$ git diff
diff --git a/tango_with_django_project/urls.py b/tango_with_django_project/urls.py
index c385489..85abbc4 100644
--- a/tango_with_django_project/urls.py
+++ b/tango_with_django_project/urls.py
@@ -15,9 +15,11 @@ Including another URLconf
 """
 from django.conf.urls import url
 from django.contrib import admin
+from django.conf.urls import include
 from rango import views

 urlpatterns = [
     url(r'^$', views.index, name='index'),
+    url(r'^rango/', include('rango.urls')),
     url(r'^admin/', admin.site.urls),
 ]

url(r'^rango/', include('rango.urls'))の重要な部分はinclude('rango.urls')だ。これはrango/から始まるURLのマッピング処理をrango.urlsに任せる、という意味になる。rango.urlsとは言うまでもなく、rangoアプリケーションの下にあるurlsというモジュール(あるいはrango/urls.pyと言い換えることもできる)のことだ。この設定に従い、rangoディレクトリにurls.pyというファイルを作成する。tango_with_django_project/urls.pyをコピペして作ればよい。具体的には以下のようになる。

1
2
3
4
5
6
7
8
$ cat rango/urls.py
from django.conf.urls import url

from rango import views

urlpatterns = [
    url(r'^$', views.index, name='rango_index'),
]

記述内容は先述したとおりなので、ここでは割愛する。重要なのはr'^$'だ。include('rango.urls')によってリクエスト情報が渡されるわけだが、マッチングするURLからrango/が削除される。例えば、rango/my-pageというURLがリクエストされたとすると、rango.urlsが処理するURLはmy-page/となる。この点に注意すること。