Djangoチュートリアル②（ビューの作成）

# はじめに

[Djangoチュートリアル①（インストールとプロジェクトの作成）](https://qiita.com/honda28/items/34dceaeeb1cdddb4c9dd)に続いて、アプリを作成してみる。[はじめての Django アプリ作成、その1](https://docs.djangoproject.com/ja/3.1/intro/tutorial01/)、[現場で使える Django の教科書（基礎編）](https://www.amazon.co.jp/%E7%8F%BE%E5%A0%B4%E3%81%A7%E4%BD%BF%E3%81%88%E3%82%8B-Django-%E3%81%AE%E6%95%99%E7%A7%91%E6%9B%B8%E3%80%8A%E5%9F%BA%E7%A4%8E%E7%B7%A8%E3%80%8B-%E6%A8%AA%E7%80%AC-%E6%98%8E%E4%BB%81/dp/4802094744)を参考にする。

# Polls アプリケーション作成

チュートリアルにしたがって、Polls アプリを作成する。（Polls は「世論調査」を意味するらしい。どんなアプリになるのか検討がつかない。。。）
アプリは Python パス上のどこにでも置けるがここでは manage.py と同じディレクトリ（ mysite 配下）に作成する。基本的には、プロジェクトが1番外側の大きな箱で、その中に複数のアプリケーションを追加していくといった構成となる。

```
$ cd mysite
$ python manage.py startapp polls
# polls ディレクトリ以下のファイルが自動で作成される
mysite       (<- ベースディレクトリ)
|-- manage.py
|-- config   (<- 設定ディレクトリ)
|   |-- __init__.py
|   |-- asgi.py
|   |-- settings.py
|   |-- urls.py
|   `-- wsgi.py
`-- polls    (<- アプリケーション)
    |-- __init__.py
    |-- admin.py
    |-- apps.py
    |-- migrations
    |   `-- __init__.py
    |-- models.py
    |-- tests.py
    `-- views.py
```

（[Djangoチュートリアル①（インストールとプロジェクトの作成）](https://qiita.com/honda28/items/34dceaeeb1cdddb4c9dd)で config を作成したためここでは config が存在するが、`$ django-admin startproject mysite` でプロジェクトを作成した場合は config ではなく mysite となる。）

# ビューの作成

ビューはリクエストに応じたレスポンスを返すという役割を持つ。Web アプリケーションでは、①ブラウザがリクエストを送信、② URLconf に登録された設定に基づいて、リクエストされた URL にマッチするビューを呼び出す、③ブラウザにレスポンスを返す、といった流れになっている。（実際は DB が関わってきたりともっと複雑だが、シンプルな例だとこんな感じのはず。）
以下でビューと URLconf の設定をして単純な例を試してみる。ビューは polls/views.py に、 URLconf の設定は config/urls.py に記述する。

## polls/views.py

ビュー関数の書き方には、①関数ベース、②クラスベースの大きく2通りの書き方がある。[現場で使える Django の教科書（基礎編）](https://www.amazon.co.jp/%E7%8F%BE%E5%A0%B4%E3%81%A7%E4%BD%BF%E3%81%88%E3%82%8B-Django-%E3%81%AE%E6%95%99%E7%A7%91%E6%9B%B8%E3%80%8A%E5%9F%BA%E7%A4%8E%E7%B7%A8%E3%80%8B-%E6%A8%AA%E7%80%AC-%E6%98%8E%E4%BB%81/dp/4802094744)では②クラスベースの書き方を推奨しているが、ここでは[はじめての Django アプリ作成、その1](https://docs.djangoproject.com/ja/3.1/intro/tutorial01/)にしたがって①関数ベースでの書き方を採用することとする。（②クラスベースの書き方についても理解したのち書きたい。）

```python:polls/views.py
from django.http import HttpResponse

def index(request):
    return HttpResponse("Hello, world. You're at the polls index.")
```

index() 関数はリクエストに対して決められた文字列（"Hello, world. You're at the polls index."）を返すシンプルな関数となっている。

## polls/urls.py と config/urls.py

上記では config/urls.py に URL 設定を記述すればよいと書いたが、設定数が多くなると管理が大変になるため、アプリケーションごとに urls.py を作成することでわかりやすくする。具体的には、 Polls アプリに関する URL 設定を polls/urls.py に記述し、各アプリの URL 設定を config/urls.py で読み込む、という構造になる。アプリケーション作成時に polls/urls.py ファイルの自動作成はされないため `$ touch polls/urls.py` で作成し、以下コードを記述する。

```python:polls/urls.py
from django.urls import path

from . import views

app_name = 'polls'
urlpatterns = [
    path('', views.index, name='index'),
]
```

URLconf は urlpatterns という名前のリスト型変数に　URL パターンとビュー関数の対応関係を追加することで設定できる。django.urls.path() 関数は第1引数に URL パターンを指定し、第2引数に URL パターンにマッチするビュー関数を指定することで設定ができる。name は URL パターンに名前をつけることができ、それにより URL を逆引きすることができる。また app_name はアプリケーションごとの urls.py に付けられる名前空間で、これも逆引きに使えるため設定しておいたほうがよいとのこと。（基本的に appn_name は アプリケーション名と同じにしておけばよいらしい。）

次に config/urls.py に上記で作成した polls/urls.py モジュールの記述を反映させる。具体的には、① django.urls.include の import、② urlpatterns のリストに include() の追加。

```python:config/urls.py
from django.contrib import admin
from django.urls import include, path

urlpatterns = [
    path('polls/', include('polls.urls')),
    path('admin/', admin.site.urls),
]
```

django.urls.include() 関数は他の URLconf を参照できる関数である。path('polls/', include('polls.urls')) により polls/ で始まる URL パターンのすべてを polls/urls.py で登録した URLconf から参照するようになっている。このように config/urls.py に全設定を記述しなくても、各アプリで設定した urls.py を include することができる。
（※ path('admin/', admin.site.urls) は管理サイトを表しているらしい。 [http://localhost:8000/admin/](http://localhost:8000/admin/) でアクセスすることはできるが、詳細はわかっていないため現段階では言及しない。）

これで index ビューを URLconf に紐付けができた。下記コマンドを実行して [http://localhost:8000/polls/](http://localhost:8000/polls/) にアクセスすると polls/views.py で定義した __Hello, world. You're at the polls index.__ が表示されるのが確認できる。今回の場合、config/urls.py にて 'polls/' を、polls/urls.py では '' を指定していたため、 [http://localhost:8000/polls/](http://localhost:8000/polls/) で views.index() を呼び出すこととなる。

```
$ python manage.py runserver
```

# おわりに

[はじめての Django アプリ作成、その1](https://docs.djangoproject.com/ja/3.1/intro/tutorial01/)のチュートリアルだけでは内容がよく理解できなかったので、[現場で使える Django の教科書（基礎編）](https://www.amazon.co.jp/%E7%8F%BE%E5%A0%B4%E3%81%A7%E4%BD%BF%E3%81%88%E3%82%8B-Django-%E3%81%AE%E6%95%99%E7%A7%91%E6%9B%B8%E3%80%8A%E5%9F%BA%E7%A4%8E%E7%B7%A8%E3%80%8B-%E6%A8%AA%E7%80%AC-%E6%98%8E%E4%BB%81/dp/4802094744)を読みながらチュートリアルを進めた。[はじめての Django アプリ作成、その2](https://docs.djangoproject.com/ja/3.1/intro/tutorial02/)を続けてやっていく予定。

関連記事のリンクは以下。
- [Djangoチュートリアル①（インストールとプロジェクトの作成）](https://qiita.com/honda28/items/34dceaeeb1cdddb4c9dd)
- [Djangoチュートリアル③（モデルの作成、Django Admin）](https://qiita.com/honda28/items/04bc74c28b816aa10e2c)
- [Djangoチュートリアル④（テンプレート）](https://qiita.com/honda28/items/f62dc31e470ef3901706)
- [Djangoチュートリアル⑤（汎用ビュー）](https://qiita.com/honda28/items/7150a5df0213dc6a3927)
- [Djangoチュートリアル⑥（自動テスト）](https://qiita.com/honda28/items/f21fe43d29ffe7e15b5d)
- [Djangoチュートリアル⑦（静的ファイル）](https://qiita.com/honda28/items/bd0bfe8731a17609907c)