DjangoでToDoList開発Part5

こんにちは、にわこまです。

今回は、ToDoを削除するページを作成します。追加したけど必要なくなった場合などに削除機能が役立つと思います。

 

「DjangoでToDoList開発」シリーズはDjangoのチュートリアルとして利用されることを目的としています。そのため、誤字脱字や分かりにくい点がございましたら、ご連絡お願い致します。

 

 

スポンサードサーチ


DjangoでToDoList開発Part5

今回は、ToDoを削除するページを作成していきます。イメージとしては、トップページに削除ボタンを追加してToDoを削除する感じです。削除ページに移動したらToDoのタイトルや内容が表示されて、確認できるようにします。

 

開発手順としては、削除用のフォーム(forms.py)の作成、削除ページ(todoDelete.html)の作成、表示処理と削除処理(views.py)の作成の順で行います。

 

 

forms.pyの編集

削除ページで表示するデータをひとまとめにするため、todolist/forms.pyを編集します。ファイルに1番下の行に追記します。

class todoDeleteForm(forms.Form):
    title = forms.CharField(label="Title", max_length=200)
    contents = forms.CharField(label="Contents", widget=forms.Textarea)
    entryDate = forms.DateField(label="Entry Date")
    deadline = forms.DateField(label="Deadline")
    done = forms.BooleanField(label="Completed?", required=False)

 

コードの解説

2行目の「title」は、ToDoのタイトルを表示するフォームです。モデルやtodoAddFormと同じくCharFieldを設定します。さらに、max_lengthを200と設定します。

 

3行目の「contents」は、ToDoの内容を表示するフォームです。todoAddFormと同じくCharFieldを設定します。また、widgetはTextareaとします。

 

4,5行目の「entryDate」と「deadline」は、記入日と締切日を表示するフォームです。モデルと同じくDateFieldを設定します。

 

6行目の「done」は、ToDoを完了済かそうでないかを表示するフォームです。モデルと同じくBooleanFieldを設定します。また、requiredをFalseに設定します。

requiredは、値の代入が必須であるかないかについて設定するためのものです。デフォルトはrequired=Trueと設定されています。つまり、値の代入が必須であるという設定になっています。
フォームでは、「csrf_token」が設定されるため空のデータを送ることができません。しかし、required=Falseと設定することで空のデータを送ることができます。

 

 

スポンサードサーチ


削除ページの作成

templates/todolist/にtodoDelete.htmlを作成し、編集します。

{% extends 'todolist/base.html' %}

{% block title %}ToDoDeleteForm{% endblock %}

{% block contents %}
<article class="tododel">
  <div class="page-name">
    <h1>ToDo削除フォーム</h1>
  </div>
  <div class="tododel-form">
    <form action="{% url 'todoDelete' del_id %}" method="post">
      {% csrf_token %}
      {% for field in form %}
        <div class="field-row">
          {{ field.label_tag }}{{ field }}
        </div>
      {% endfor %}
      <p>本当に削除しますか?</p>
      <input type="submit" value="Delete">
    </form>
  </div>
</article>
{% endblock %}

 

コードの解説

1行目の「{% extends ‘todolist/base.html’ %}」は、base.htmlを拡張してtodoDelete.htmlを作成するという宣言です。

 

3行目の「{% block title %}ToDoDeleteForm{% endblock %}」は、タイトルブロックにToDoDeleteFormを代入しています。

 

5行目~23行目は、contentsブロックに代入するコードです。 12行目の「{% csrf_token %}」は、アプリケーションの脆弱性を突く攻撃を防ぐためのものです。formを書くならば、必ず必要なものです。

csrfとは、クロスサイトリクエストフォージェリのことです。アプリケーションの脆弱性を突く攻撃方法のことです。

13行目~17行目は、forブロックです。繰り返し処理がされています。formからlabelとfieldが取り出されています。

 

最後に、11行目で指定したURL「todoDelete」は、後でurls.pyで指定するため覚えておきます。

 

現在のフォルダ状況(templates/todolistから)

templates
   |- todolist
         |- base.html
         |- index.html
         |- todoAdd.html
         |- todoDelete.html  # 追加部

 

 

views.pyの編集(表示処理)

削除するToDoを表示する処理を作成します。todolist/views.pyを編集します。

from django.shortcuts import render
from django.shortcuts import redirect
from django.http import HttpResponse

from .models import MyToDoList

from .forms import todoAddForm, todoDeleteForm  # todoDeleteFormを追加
   ・
   ・
   ・
   省略
   ・
   ・
   ・
# === ここから 追加 ===
def todoDelete(request, del_id):
    mtdl_obj = MyToDoList.objects.filter(id=del_id).first()
    context = {
        'title':mtdl_obj.title,
        'contents':mtdl_obj.contents,
        'entryDate':mtdl_obj.entryDate,
        'deadline':mtdl_obj.deadline,
        'done':mtdl_obj.done,
    }
    form = todoDeleteForm(context)
    params = {
        'del_id':del_id,
        'form':form
    }
    return render(request, 'todolist/todoDelete.html', params)
# === ここまで 追加 ===

 

コードの解説

7行目は、forms.pyにあるtodoDeleteFormを使うという宣言を行っています。

 

17行目の「mtdl_obj = MyToDoList.objects.filter(id=del_id).first()」は、削除するToDoのデータをMyToDoListモデルから抽出しています。

 

18行目~24行目は、todoDeleteFormに削除するToDoのデータを辞書型で設定しています。辞書型のkeyの文字列はtodoDeleteFormで設定した変数名です。

 

25行目の「form = todoDeleteForm(context)」は、todoDeleteFormに削除するToDoのデータを対応させています。これにより、削除ページでは空欄のフォームではなく、値が入ったフォームが表示されます。

 

26行目~29行目は、todoDelete.htmlで使う変数を辞書型で設定しています。del_idはURLのところで使います。

 

30行目は、renderによってtodoDelete.htmlにparamsを指定しています。これにより、todoDelete.html内でdel_idとformが使えるようになります。

 

urls.pyの編集

viewsを作成したためURLを設定します。todolist/urls.pyを編集します。

from django.urls import path

from . import views

urlpatterns = [
    path('', views.index, name='index'),
    path('todoAdd', views.todoAdd, name='todoAdd'),
    path('todoDelete/<int:del_id>', views.todoDelete, name='todoDelete'),  # 追加部
]

 

pathの第1引数「’todoDelete/<int:del_id>’」は、スラッシュ移行のdel_idによって削除したいToDoを指定することができます。また、del_idの部分はviews.pyの関数の引数に指定したものを代入する。

「path(‘aaa/<int:x>’, views.bbb, name=’ccc’)」のようなURLをHTMLファイル内で使いたい場合は、「{% url ‘ccc’ x %}」のように記述します。xは数字です。

 

今回追加したURLの名前は、todoDelete.htmlでformに設定したURLです。具体的には、pathの第3引数「name=””」にtodoDeleteを設定します。

 

動作確認

削除したいデータが正しく表示されるか確認するため、サーバを起動します。

python manage.py runserver

 

サーバを起動したら、「http://localhost:8000/todolist/todoDelete/1」にアクセスします。最後の数字が1でエラーがでる場合は他の数字で確認します。私の場合は以下のように表示されました。

 

データが表示されたことを確認したら、Deleteボタンをクリックします。その後、トップページに移動します。以下のように表示されます。

 

削除したはずのデータが削除されていないことを確認できると思います。views.pyのtodoDeleteに削除処理を記述していないからです。

 

 

スポンサードサーチ


views.pyの編集(削除処理)

Deleteボタンを押した後の削除処理を作成します。todolist/views.pyを編集します。

def todoDelete(request, del_id):
    mtdl_obj = MyToDoList.objects.filter(id=del_id).first()
    # === ここから 追加 ===
    if(request.method == 'POST'):
        mtdl_obj.delete()
        return redirect(to='/todolist/')
    # === ここまで 追加 ===
    context = {
        'title':mtdl_obj.title,
        'contents':mtdl_obj.contents,
        'entryDate':mtdl_obj.entryDate,
        'deadline':mtdl_obj.deadline,
        'done':mtdl_obj.done,
    }
    form = todoDeleteForm(context)
    params = {
        'del_id':del_id,
        'form':form
    }
    return render(request, 'todolist/todoDelete.html', params)

 

コードの解説

4行目~6行目は、Deleteボタンがクリックされた後の処理です。

5行目の「mtdl_obj.delete()」は、del_idのデータを削除します。

6行目は、redirect関数によってトップページにリダイレクトします。

 

トップページの編集

「views.pyの編集(表示処理)」の動作確認で行ったような、del_idを手動で指定する方法はエラーになる可能性があるためトップページの「完了/未完了」の隣に、そのデータに対応する削除ボタンを追加します。

templates/todolist/index.htmlを編集します。

<!-- 上記省略 -->
<table>
  <tr class="tb-header">
    <th>Title</th>
    <th>記入日</th>
    <th>締切日</th>
    <th>完了/未完了</th>
    <th>削除ボタン</th>  # 追加部
  </tr>
  {% for tdl in todolist %}
    <tr class="tdl">
      <td class="title">{{ tdl.title }}</td>
      <td class="entry-date">{{ tdl.entryDate|date:"n/j" }}</td>
      <td class="deadline">{{ tdl.deadline|date:"n/j" }}</td>
      <td ckass="done">
        {% if tdl.done == False %}
          <label>未</label>
        {% elif tdl.done == True %}
          <label>済</label>
        {% endif %}
      </td>
      <td class="btn-del"><a href="{% url 'todoDelete' tdl.id %}">Delete</a></td>  # 追加部
    </tr>
  {% endfor %}
</table>
<!-- 下記省略 -->

 

動作確認

トップページに削除ボタンが追加されたことの確認とデータが削除されるかの確認を行うため、サーバを起動します。

python manage.py runserver

 

サーバを起動させたら、「http://localhost:8000/todolist/」にアクセスします。私の場合は以下のように表示されます。

 

いずれかのDeleteボタンをクリックします。削除ページが表示されます。私の場合は以下のように表示されます。

 

削除したいデータが表示されたことを確認したら、Deleteボタンをクリックします。リダイレクトを設定しているため、自動でトップページに移動します。

 

削除ページで表示されていた、タイトルが「title」というデータが削除されたことを確認できます。以上で動作確認と削除ページの作成は完了です。

 

 

まとめ

今回は、削除ページを作成しました。削除用のフォームを作成してデータを代入することで、ブラウザでは、データが入力された状態で表示させることができます。

 

削除ページでは、データ1つひとつのページが必要であるためURLによってページを分けられるようにしました。

 

次回は、ToDoを編集するページを作成します。締切日の修正や内容を変更したいときに役立つと思います。

 

最後までお読みいただきありがとうございます。


スポンサードサーチ