DjangoのDeleteView/CreateViewの実装方法を理解する

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

前回、ListViewとDetailViewの実装方法理解の為にToDoのWebアプリの作成を行いました。
今回は同じTodoアプリに機能を追加していく形でDeleteViewとCreateViewを実装していきたいと思います。前回の記事は以下となりますので、併せて参考にしていただければと思います。

https://qiita.com/ohtsuka-shota/items/0e651df83ce5415628f8

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

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

# 環境構築
## 環境イメージ
deleteCreateTestPJという名前のプロジェクトを作成し、todoAppという名前のアプリケーションを作成しております。
ファイル単位で前回から増えたところはDeleteViewとCreateViewを実装するためのHTML/CSSくらいかと思います。コードベースではアプリ側のurls.pyやviews.pyに対して記載が増えています。
![django-ページ11.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/7572de6c-f063-9361-4070-3c41b8ca4481.png)

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

<!DOCTYPE html>
    <html lang="ja">

    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width">
        <title>新規todo作成</title>
        <link href="{% static 'todoStyleSheet/todoCreateStyle.css' %}" rel="stylesheet">
    </head>

    <body>
        <div>
            <div class="header-container">
                <h1 class="title">task作成</h1>
            </div>
            <form method="post" action="{% url 'todoApp:todoCreatePage' %}" class="form-group">{% csrf_token %}
                <div class="task-create-form">
                    <h3>タスク名</h3>
                    <input class="task-create-content" type="text" placeholder="Title"
                    name="{{ form.title.html_name }}" autofocus="" autocapitalize="none" maxlength="100" required="">
                </div>                
                <div class="task-create-form">
                    <h3>タスク詳細</h3>
                    <textarea class="task-create-content"
                    name="{{ form.memo.html_name }}" autofocus="" autocapitalize="none" maxlength="250" required="">
                    </textarea>
                </div>
                <div class="task-create-form">
                    <h3>タスク優先度</h3>
                    <select class="task-create-content" name="{{ form.priority.html_name }}" required="">
                        {% for value, label in form.fields.priority.choices %}
                            <option value="{{ value }}">{{ label }}</option>
                        {% endfor %}
                    </select>
                </div>
                <div class="task-create-form">
                    <h3>タスク完了期日</h3>
                    <input class="task-create-content" type="date" placeholder="Deadline"
                           name="{{ form.deadline.html_name }}" autofocus="" autocapitalize="none" maxlength="250" required="">
                </div>
                
                <div id="submit-form">
                    <button id="task-create-button" type="submit">task作成</button>
                    <button type="button" class="btn" onclick="window.location.href='{% url 'todoApp:todoListPage' %}'">リストに戻る</button>
                </div>
                    
            </form>
        </div>
    </body>
    
    </html>
```
- ユーザからデータの入力を受け付けるためのWebページをつかさどるHTMLになりますが、気を付けたいのはデータの型。models.pyで設定されている型と同じでないと、データが上手くDBに格納されないです。

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

app_name = "todoApp"

urlpatterns = [
    path("list/", todoListView.as_view(), name="todoListPage"),
    path("detail/<int:pk>", todoDetailView.as_view(), name="todoDetailPage"),
    path("create/", todoCreateView.as_view(), name="todoCreatePage"),
    path("delete/<int:pk>", todoDeleteView.as_view(), name="todoDeletePage"),
]
```
- deleteのページに遷移させる時もdetailの時と同じように<int:pk>と指定してあげるだけで良いようです。便利ですね。

### todoApp/views.py
```todoApp/views.py
# todoApp views.py

from django.shortcuts import render
from django.views.generic import ListView, DetailView, DeleteView, CreateView
from .models import todoTable
from django.urls import reverse_lazy

class todoListView(ListView):
    template_name = "todoList.html"
    model = todoTable

class todoDetailView(DetailView):
    template_name = "todoDetail.html"
    model = todoTable

class todoDeleteView(DeleteView):
    template_name = "todoDelete.html"
    model = todoTable
    success_url = reverse_lazy("todoApp:todoListPage")

class todoCreateView(CreateView):
    template_name = "todoCreate.html"
    model = todoTable
    fields = ("title", "memo", "priority", "deadline")
    success_url = reverse_lazy("todoApp:todoListPage")
```

- DeleteViewを継承する際もsuccess_urlを指定して削除成功後にどのページに遷移させるかを指定するようです。

# 実行結果
タスク一覧は以下のようなレイアウトとなっております。
画面右上にあるtodo作成ボタンを押下してみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/471bf29f-d416-f835-5ea8-28972ae2ec5b.png)
todoを作成する画面は以下のようになっています。それぞれ入力し左下のtask作成を押下します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/4f903662-f710-1e84-4513-9e9717cc63c9.png)
ListViewやDetailViewでうまく表示されていることが確認できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/60b68f18-f03c-d066-f953-9eb364fd0dae.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/8f6c85e2-b3d2-7c8c-88b5-eb50023df4f9.png)
作成したものを削除してみます。各todoに表示されている赤いボタンを押下すると以下のような画面が表示されます。左下にある削除を実行を押下します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/cce16fef-2d7e-d0c9-6578-6fb8bbce2664.png)
ListViewから消えていることが確認できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/8cf021eb-72ed-21a0-a2d9-b4c7920d53bf.png)