「DjangoでTODOリストを作ろう!その1」では、Djangoを使ってTODOリストのアプリケーションを作成し、タスクを表示する方法を学びました。
今回はシリーズ第1回として、TODOリストの基本的な部分を実装していきます。 TODOリストをブラウザに表示できることを目標に、取り組んでいきましょう! この記事を読んで取り組むことで、Djangoの基本的な要素である以下を習得する[…]
今回は、「その1」で作成したTODOリストに、新しいタスクを追加する方法を学びましょう。
この記事を読んで取り組むことで、以下を習得することができます。
- フォームの作成
- データベースへのデータの保存方法
- POSTリクエストの処理
- テンプレートへのフォーム表示
今回作成するのは以下の完成画面におけるタスク追加フォームです。
タスク一覧の一番下に配置することで、感覚的に操作できるようになっていますね。
それでは、早速始めていきましょう。
DjangoでTODOリストを作ろう!その2:タスクを追加しよう
タスク追加用にurls.pyを作成する
前回の記事で説明したように、機能を作る場合にはModel→View→Template→urls.pyの順で作るのがおススメです。
一方で今回のようにModelに対する変更がない場合にはurls.py→View→Templateの順で作ると分かりやすくておススメです。
それではタスク追加用のコードをurls.pyに追記していきましょう。
djangotodo/urls.pyに以下のように追記してください。
1 2 3 4 5 6 7 |
from django.urls import path from .views import TaskList, TaskCreate urlpatterns = [ path('', TaskList.as_view(), name='task_list'), path('create/', TaskCreate.as_view(), name='task_create'), #追記 ] |
これでdjangotodo/create/というURLにアクセスしたときに、TaskCreateというビュークラスが起動するようになります。
念のためにこのURLルートにはtask_createという名前を付けておきましょう。
次に、Viewsにタスク追加処理を入れる作業を行います。
タスク追加用のフォームを司る、forms.pyを作成する
さて、それではviewsの編集をと行きたいところですが、今回はクラスベースビューではなく、forms.pyを用いて追加機能を実装していきましょう。
forms.pyを用いることでクラスベースビューの際には必要だったページの移動やテンプレートの指定がなくなり、タスク一覧表示画面にタスク追加フォームを表示することができます。
まず、djangotodoフォルダの中にforms.pyというファイルを作成します。自動作成すればそちらを編集するようにしてください。
forms.pyに以下のように記載しましょう。
1 2 3 4 5 6 7 8 9 10 11 |
from django import forms from .models import Task class TaskForm(forms.ModelForm): #1.HTMLの入力フィールドをカレンダーに変換 due_date = forms.DateField(widget=forms.DateInput(attrs={'type': 'date'}), required=False) #2.フォームに対応するModelとフィールドを指定する class Meta: model = Task fields = ('title', 'due_date') |
以下、説明です。
due_dateは期限日を表しますが、デフォルトではテキストボックスになってしまいます。
少し不親切ですので、タスク追加のフォームではHTMLのカレンダーボックスを表示するようにしています。
forms.pyにおいては上記のようにwidgetを指定することで、お好きな入力フォームを指定することが可能です。
今回はタスク名であるtitleと期限日であるdue_dateです。
たったこれだけ指定するだけで、データベースとリンクするフォームを作成することが可能です。
さて、これでforms.pyは作成が終ったので、viewsの追記を行いましょう。
タスク追加フォームを表示するために、リスト表示のViewを編集する
タスクの追加フォームはタスク表示のページに表示するために、TaskListのクラスを編集します。
以下のように追記してください。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
from .forms import TaskForm class TaskList(ListView): model = Task template_name = 'task_list.html' context_object_name = 'tasks' ordering = ['-created_at'] def get_context_data(self, **kwargs): #1.コンテキストを取得 context = super().get_context_data(**kwargs) #2.コンテキストにフォームをセット context['form'] = TaskForm() return context |
上半分は変わりませんが、get_context_dataを追記しています。以下詳細です。
デフォルトで定義されているget_context_dataを取得しています。
contextはテンプレートに渡す箱のようなもので、ここで取得した箱に中身を追加していくイメージです。
箱の中にformという名前を付けてTaskFormを追加しています。こちらは先ほど作成したforms.pyの中身です。
フォームを丸ごと箱の中に入れたので、テンプレートにて「form」という名前でフォームを表示することが可能です。
TaskForm()はインポートしないと使えないので、必ずviews.pyの先頭で宣言するようにしてください。
さて、この調子でタスクの追加処理も記載してしまいましょう。
タスク追加処理を追加する
フォームの表示が出来たので、次にデータベースにデータを追加する処理を加えていきましょう。
今開いているviews.pyに以下のクラスを追記します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
from django.shortcuts import redirect from django.views import View -- 省略 -- class TaskCreate(View): #送信されたフォーム内容のDB処理 def post(self, request): #1.送信データのチェック form = TaskForm(request.POST) #2.問題がなければ登録 if form.is_valid(): task = form.save() #3.タスク一覧へ遷移 return redirect('task_list') |
以下、説明です。
作成したクラスTaskFormにPOST送信されたフォーム内容を格納しています。
異常な値を入力されていないかのチェックに使用しています。
フォームに問題がないかを確認しています。
is_valid()はフォームのバリデーションに問題があるかどうかで分岐処理を行います。
問題がなければ後続の「task = form.save()」で、データベースにデータを保存しています。
最後にタスク表示画面に遷移しています。これでタスクの追加に成功しようと失敗しようと、リスト表示画面に戻るようになります。
タスク追加フォームを表示するHTMLを作成する
urls.pyとViewの作成が完了したので、次はテンプレートを作成します。
今回は、タスク追加フォームをtask_list.htmlとは別に作成していきましょう。
まず、djangotodo/templatesフォルダの中に新しく「task_form.html」というファイルを作成します。その中身は以下のようにします。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<!-- 1.フォーム送信でViewを起動 --> <form method="post" action="{% url 'task_create' %}"> <!-- 2.CSRFトークン --> {% csrf_token %} <tr> <!-- 3.フォーム内容を表示 --> <td>{{ form.title }}</td> <td>{{ form.due_date }}</td> <td> <button type="submit" class="btn btn-primary">タスク追加</button> </td> </tr> </form> |
HTMLのaction属性にタスク追加処理のURLを設定することで、「タスク追加」ボタンを押したときにデータベースに追加しています。
Djangoにおけるクロスサイトリクエストフォージェリ攻撃を防止するタグです。
データを送信するフォームを実装する場合は、必ずformタグの直後に入れるようにしてください。
追加フォームはformという名前で渡されているので、その後にtitleやdue_dateを指定することでそれぞれの入力フォームを出力します。
このようにフォームを別HTMLファイルに分けることはよくやることで、同じフォームを複数の場所で使い回したい場合に便利です。
また、何か修正があった場合には、このtask_form.htmlだけを編集するだけで済むためメンテナンス性が高くなります。
しかし、このままではタスク追加フォームが表示されませんので、task_list.htmlを編集する必要があります。
タスク追加フォームをタスク表示のHTMLでincludeする
別のHTMLにHTMLファイルを埋め込むには、「includeタグ」を用います。
task_list.htmlに以下のように追記してください。
1 2 3 4 5 6 7 8 9 |
<tbody> -- 省略 -- {% empty %} <tr> <td colspan="4">タスクがありません</td> </tr> {% endfor %} {% include 'task_form.html' with form=form %} </tbody> |
{% endfor %}タグの下に記載します。これでtask_form.htmlの中身が表示されます。
with form=formはViewから渡すフォームを、このtask_list.htmlからtask_form.htmlに渡しています。
これをしないとフォームが表示されないので要注意です。
タスク追加ができるか確認しよう!
準備が整ったので、実際にアクセスしてタスクを追加してみましょう。
ページにアクセスして、以下のように追加用のフォームが表示されれば成功です。
ちゃんとフォームが表示されましたね。タスクや期日を入れるなどして、「タスク追加」ボタンを押してみてください。
タスクが追加できましたね。
おわりに
前回と同じく、ここまでのソースはGithubに掲載しておくので、もしも見返したい場合は確認してみてください。
今回はタスクの追加を行ったので、次の記事ではタスクの編集を行っていきましょう。
前回の記事では、タスクを追加する方法について学びました。 [sitecard subtitle=関連記事 url=https://freemas.stepupkaraoke.com/python/django/making-todol[…]