Todoリストの詳細画面、作成画面、削除画面、更新画面を作っていきましょう。
DetailViewの作成
DetailViewは本棚アプリで作ったものとほとんど同じです。
ブロックを使うので少しコードが変わってきますが、ブロックの使い方も前回のlistの部分で学んでいますので、コードだけご紹介します。
コマンドライン-BASE/templates
$ touch detail.html
コード-BASE/templates/detail.html
{% extends 'base.html' %}
{% block header %}
<h1>投稿詳細画面</h1>
{% endblock %}
{% block content %}
<p>タイトル:{{ object.title }}</p>
<p>Todoの内容:{{ object.content }}</p>
<p>担当者:{{ object.pic }}</p>
{% endblock%}
CreateViewの作成
作成画面を作るには、CreateViewを使います。
ListViewがデータ一覧、DetailViewがデータの詳細、それに対し、データの作成がCreateViewです。
早速Viewを作っていきましょう。
コード-BASE/todo/views.py
...
class TodoCreateView(CreateView): ← new!
model = TodoModel ← new!
template_name = create.html ← new!
fields = ['title', 'description', 'pic'] ← new!
ListViewとほとんど同じですが、最後の行のfieldsだけ新しい項目です。
このfieldsは、htmlにフォームとして埋め込む時に使われます。
今回は、モデルで定義した3つ(title、description、pic)を全て使うので3つとも書いていますが、使わないフィールドがある場合はここに書く必要はありません。
では、ここで書いたフィールドがhtmlファイルでどのように表示されるのでしょうか?
早速htmlファイル(create.html)を作って、コードを書いていきましょう。
コマンドライン-BASE/templates
$ touch create.html
コードBASE/templates/create.html
{% extends 'base.html' %}
{% block header %}
<h1>新規Todo投稿画面</h1>
{% endblock %}
{% block content %}
<form action = "" method ="post">{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="投稿する">
</form>
{% endblock %}
コードの解説1 {% csrf_token %}
このcsrfというのは、cross site request forgeryの略です。セキュリティ上のリスクを防ぐためにdjangoが用意している対策です。
formを使う時には、このcsrf_tokenを使うようにしましょう。
2 {{form.as_p}}
これもdjangoに備わった機能です。form.as_pとすることで、pタグで囲まれる形でフォームの内容を表示することができるようになります。
(form.as_pの詳細については、form.as_pの意味をわかりやすく解説という記事を参考にしてください。)
form.as_pにいてどのフォームが表示されるのかというと、views.pyファイルで指定したモデルです。(今回の場合、CreateViewで指定したToDoModelです。)
そして、ToDoModelはmodels.pyファイルの中で、3つのフィールドを作りました。
ですので、CreateViewを継承することにより、htmlファイルの中で{{ form }}という記載をすることで、ToDoModelに対応したフォームの項目を呼び出すことができるようになるのです。
formは個別に表示することもできる。
上記の例では、pタグで囲むことでフォームの内容を表示しましたが、個別に表示することもできます。
{{form.as_p}}と同じ内容を、個別に書き換えたものがこちらです。
コード<p>
{{form.title}}
{{form.description}}
{{form.pic}}
</p>
このように書くことでフォームを入力させることができます。
フォームにデータを入れた後に移動するurlは?
このフォームは、action=""と、送信ボタンを押した後に遷移するurlが書かれていません。
djangoは、データを送信した後にどのurlに遷移させるのかを設定することができる機能を持っています。
少し細かく説明すると、htmlのファイル上でフォームの情報を送信したとき、djangoがその情報を受け取ります。
そして、受け取った情報をもとに、つぎにどのurlに遷移させるかを指定するのです。
そして、この設定はviewの中で行っていきます。
実際のやり方をみていきましょう。
ボタンを押した後に遷移するurlの指定方法
コードviews.pyファイルを編集していきましょう。
-BASE/todo/view.py
from .models import ToDoModel
from django.views.generic import CreateView
from django.urls import reverse_lazy
class ToDoCreateView(CreateView):
model = ToDoModel
fields = ['title', 'content', 'pic']
success_url = reverse_lazy('list') ← new!
最後の行に注目してください。
success_urlというコードを追加しました。
これは、CreateViewにおいてデータが無事に追加できたら遷移させるurlを指定するものです。
ですので、DeleteViewにおいてデータの削除が無事にできた時や、UpdateViewでデータの編集をしたときなども、同じようにsuccess_urlを設定することができます。
また、reverse_lazyの中には('list')という表示がありますが、これはurlpatternで指定したnameを書きます。
urls.pyファイルの中身を確認してみましょう。
コード-BASE/todo.urls.py
urlpatterns = [
path('detail', TodoListView.as_view(), name='list'),
]
name='list'という記載があることがわかります。このnameで指定した内容をreverse_lazyのかっこの中で指定することによって、Todoの作成が完了した後に遷移させるview(url)を指定することができるようになります。
削除画面の作り方
次に、削除画面を作っていきましょう。
削除画面を作るためには、DeleteViewを使います。
実際のコードを見て理解していった方が早いと思いますので、コードを書いていきましょう。
コード-BASE/task/views.py
class TodoDelete(DeleteView):
model = TodoModel
success_url = reverse_lazy('list')
削除画面は、新規投稿(CreateView)と同じようなイメージで作成していくだけです。
具体的なコードでみていきましょう。
コード-BASE/templates/delete.html
<form method="post">{% csrf_token %}
<p>本当に "{{ object }}" を削除しますか?</p>
<input type="submit" value="削除する">
</form>
UpdateViewの作成
最後にUpdateViewの作成をしていきましょう。
UpdateViewも基本的には今までつくったCreateViewやDeleteViewと同じようなイメージです。
つまり、対象となるTodoを呼び出し、内容を変更し、変更ボタンを押すと内容が変更されるという形です。Djangoでは簡単にUpdateViewの実装をすることができます。
実際にコードを書いていきましょう。
コード-BASE/templates/update.html
{% extends 'base.html' %}
{% block header %}
<h1>新規Todoの作成</h1>
{% endblock %}
{% block content %}
<form action='' method='post'>{% csrf_token %}
{{ form.as_p }}
<input type='submit' value='Todoを作成する"></form>
{% endblock %}
これはcreate.htmlとほとんど同じです。
次に、views.pyの作成をしていきましょう。
コード-BASE/todo/views.py
...
class TodoUpdateView(UpdateView):
model = ToDoModel
template_name = 'update.html'
fields = ['title', 'content', 'pic']
success_url = reverse_lazy('list')
これもCreateViewとほとんど同じです。
これで新しい3つのClassBasedViewを作ることができました。
urls.pyファイルを編集して、urlとviewの繋ぎこみをしていきましょう。
コードBASE/todo/urls.py
from django.urls import path
from .views import ToDoListView, ToDoDetailView, ToDoCreateView, ToDoUpdateView
urlpatterns = [
path('list/', ToDoListView.as_view(), name='list'),
path('detail/<int:pk>', ToDoDetailView.as_view(), name='detail'),
path('delete/<int:pk>', ToDoDeleteView.as_view(), name='delete'),
path('create/', ToDoCreateView.as_view(), name='create'),
path('update/<int:pk>', ToDoUpdateView.as_view(), name='update'),
]
これでそれぞれの画面の設定が完了しました。
ただ、今はhtmlファイル上ではそれぞれのViewをつなぐリンクの設定がされていません。
例えば、Todoリストでの一覧において、個別のデータをクリックすると、そのTodoの詳細が表示されるような設定です。
djangoでは、リンクの設定も簡単にできるようになっています。
次の記事でリンクの使い方を学び、それぞれのViewの関連付けを行っていきましょう。