DetailView、CreateView、DeleteView、UpdateViewの作成

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の関連付けを行っていきましょう。

~Django無料講義~のご案内

Code for Djangoが、4時間超の無料Django講義をはじめました
 
・本を出版したCode for Djangoの
 製作者が作ったサイトです。
 
・Code for Djangoの内容も、
 動画で詳しく解説しています。
 
・動画は順次ふやしていきますので、
 ただで学び続けることが可能です。
 
・Djangoの効率的なスキルアップに、
 是非お役立て下さい。

                                                                 Django講義はこちら
Created with