DjangoのListView/DetailViewの実装方法を理解する

こんにちは。
株式会社クラスアクト インフラストラクチャ事業部の大塚です。

前回、CreateViewの実装方法を理解しました。
今回はListViewとDetailViewを使ってToDoのWebアプリを作成してみたいと思います。

https://qiita.com/ohtsuka-shota/items/8cf9dcd4f5206752921f

# github 
今回のコードは以下で確認できます。
適宜ご覧頂ければ幸いです。

https://github.com/ohtsuka-shota/publicDjangoStudy/tree/main/listDetailTestPJ

# 環境構築
## 環境イメージ
listDetailTestPJという名前のプロジェクトと、todoAppという名前のアプリケーションを作成しております。
![django-ページ11.drawio (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/88624d69-18b1-6350-71b0-c3f00d8bf2f9.png)

## 個人的に重要そうだと思う部分のメモ
### templates/todoList.html
```templates/todoList.html
{% load static %}

<!DOCTYPE html>
    <html lang="ja">
    
        <head>
            <meta charset="utf-8">
            <meta name="viewport", content="width=device-width">
            <title>list-detail ListPage</title>
            <link href="{% static 'todoStyleSheet/todoListStyle.css' %}" rel="stylesheet">
        </head>

        <body>
            <h1 class="title">ToDoList</h1>
            {% for todo in object_list %}
                <ul>
                <li class="todo-li">{{ todo.title }}<br>
                    <button type="button" class="btn"><a href="{% url 'todoApp:todoDetailPage' todo.pk %}" class="todo-link">詳細確認</a></button>
                </li>
                </ul>
            {% endfor %}
            <div class="btn-div"><button type="button" class="btn"><a href="{% url 'homePage' %}" class="btn">ホーム画面に戻る</a></button></div>
        </body>

    </html>
```
- link href="{% static 'todoStyleSheet/todoListStyle.css' %}" rel="stylesheet"のようにCSSファイルを指定することが出来る。今回の例ではstatic > todoStyleSheetディレクトリにあるtodoListStyle.cssを指定しています。このstaticはsettings.pyで指定していないといけないです。
- a href="{% url 'todoApp:todoDetailPage' todo.pk %
これのtodoはfor todo in object_listのtodoを示している。その後に.pkとすることでListViewとDetailViewを連携させる（リンクを張る）ことが出来る。
（ボキャブラリが無くて上手く説明できない。）
- todo in object_listのobject_listはListViewを使うとデフォルトで使用することが出来るリストになるようです。

### templates/todoDetail.html
```templates/todoDetail.html
{% load static %}

<!DOCTYPE html>
    <html lang="ja">
    
        <head>
            <meta charset="utf-8">
            <meta name="viewport", content="width=device-width">
            <title>{{ object.title }}</title>
            <link href="{% static 'todoStyleSheet/todoDetailStyle.css' %}" rel="stylesheet">
        </head>

        <body>
            <h1 class="title">{{ object.title }}</h1>
            <h3 class="sub-title">詳細<h5 class="content">{{ object.memo }}</h5></h3>
            <h3 class="sub-title">優先度<h5 class="content">{{ object.priority }}</h5></h3>
            <h3 class="sub-title">締切日<h5 class="content">{{ object.deadline }}</h5></h3>
            <div class="btn-div"><button type="button" class="btn-back"><a href="{% url 'todoApp:todoListPage' %}" class="btn-text">一覧に戻る</a></button></div>
        </body>

    </html>
```
- DetailViewではListViewの時のようにfor文を使わなくてもobjectでDBに格納されている要素を取り出すことが出来る。今回はmodelに（title,memo,priority,deadline）が格納されているが、これをobject.titleやobject.prioritのように記載することでその要素を取り出せる。

### todoAPP/urls.py
```todoApp/urls.py
from django.urls import path
from .views import todoListView, todoDetailView

app_name = "todoApp"

urlpatterns = [
    path("list/", todoListView.as_view(), name="todoListPage"),
    path("detail/<int:pk>", todoDetailView.as_view(), name="todoDetailPage"),
]
```
- DetailViewを継承するものに対してURLを指定するときはint:pkのようにパスを張らないと「どの詳細を見るのか？」ということがDjango側で分からずにエラーを返してしまう。
このint:pkのpkはadmin管理画面でDBの中身を見るときのURLで赤枠部分の番号のことの様子。これをDjango側で自動で解釈してくれているらしい。
![タイトルなし.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/a8c314fd-da72-cd14-52ac-d1d89f290f30.png)

# 実行結果
まず、今回のmodel(=DB)には以下2つのデータが格納されています。今回はadmin管理画面からデータを登録しております。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/4da2e171-5d91-8ed0-db64-bb24780a8b5d.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/e68d3576-6814-19a1-f516-af1e6cfb5cf2.png)

Djangoにアクセスするとデフォルトでは以下のような画面が表示されます。レイアウトは適当です。
Check todoListというボタンを押すとhttp\://localhost:8000/todo/list/にアクセスするようにurls.pyでルーティングしています。todo/list/はListViewを継承しているtodoListViewの処理を実行するようになっています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/f78e2f9d-b700-1259-abcc-f23eb88cb7da.png)
ボタンを押した後は以下のような画面が出ます。レイアウトは(ry。
DBに格納されているデータのtitle要素だけをこのページでは表示させ、詳細はボタンを押した先で確認できるようにしているイメージです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/a2d71300-d63e-6db7-be86-9dc4e4ce68b0.png)
ボタンを押した後は以下のように詳細を確認することが出来ます。実装してみることでListViewとDetailViewについて理解度が深まった気がしました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/8ff1ad78-1be4-e3c4-c8ef-41b05db66b61.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/cdb54c74-7a63-4c7a-8217-5033504e8e86.png)