Djangoではクラスベースビューという、簡単にビューを実装できる仕組みがあります。
クラスベースビューの中にはデータ操作に必須のCreateView、ListView、UpdateView、DeleteViewというクラスがあります。
CreateView、ListViewに関しては前回の記事で解説しましたが、今回はデータの更新ができるようになるUpdateViewと、データの削除ができるようになるDeleteViewを実装します。
Djangoに必要なHTML/CSS、JavaScriptなどのWeb開発系言語は侍テラコヤという学習サイトで無料で学習できるのでおすすめですよ!
クラスベースビューとは
クラスベースビュー(汎用クラスビュー)とは、Djangoで標準で用意されているviewを実装するためのクラス、あるいはそれを継承した自前で作成したクラスを指します。
Djangoでは、ビューを実装するために、さまざまな機能のクラスが事前に用意されています。
開発者は、それらのクラスを継承したクラスを定義することでビューを実装することが可能です。
例えば、モデルの登録済みデータをフォーム形式で更新するUpdateViewや、モデルの登録済みデータを削除するためのDeleteViewがあります。
以下、代表的なクラスベースビューをまとめます。
クラス名 | 説明 | 定義場所 |
---|---|---|
View | 最も基本的なクラスベースビュー。すべてのクラスベースビューはこのViewクラスを継承している。クラスベースビューを実装する際は、このViewクラスよりも、さまざまな機能に特化した以下のクラスを継承することが多い。 | django.views.generic.base.View |
TemplateView | Viewに続いて基本的なクラスベースビュー。特徴は、クラス変数template_nameにテンプレートファイル名を設定すると、自動的にそのテンプレートを使用する(RedirectView以外の以下のクラスはすべて同機能あり)。get時の動作しか定義されていないため、postなどは自前で作成する必要がある。 | django.views.generic.base.TemplateView |
RedirectView | リダイレクト動作に特化したクラスベースビュー。デフォルトでは、すべてのHTTPメソッド(POSTやPUTなど)も、GET時の動作に置き換えられる。 | django.views.generic.base.RedirectView |
FormView | フォーム作成に特化したクラスベースビュー。クラス変数form_classに設定したフォームの表示や、POST時のバリデーションなどが実装済み。 | django.views.generic.edit.FormView |
CreateView | データベースにデータを新規追加することに特化したクラスベースビュー。モデルに応じたフォームを表示し、PSOT時にデータを登録する。 | django.views.generic.edit.CreateView |
UpdateView | データベースのデータを更新することに特化したクラスベースビュー。既存データの修正が可能。 | django.views.generic.edit.CreateView |
ListView | データベースのデータを一覧表示することに特化したクラスベースビュー。データ数が多い場合、ページを分けるページネーションの機能が搭載。 | django.views.generic.list.ListView |
DeleteView | データベースのデータを削除することに特化したクラスベースビュー。データ削除時の確認画面を表示できる。 | django.views.generic.edit.DeleteView |
DetailView | データベースのデータ詳細を表示することに特化したクラスベースビュー。ListViewでは主要なカラムのみ表示し、DetailViewで詳細を表示する使い分けが可能。 | django.views.generic.detail.DetailView |
共通設定
次章からUpdateView、DeleteViewをそれぞれ説明しますが、models.pyとurls.py、そして前回の記事で実装したviews.pyを定義しておきます。
models.py
モデルは以下のように定義します。
内容はとても簡単で、文字列のnameと、int型のageフィールドがあるだけです。
from django.db import models
class Member(models.Model):
name = models.CharField(max_length=100)
age = models.IntegerField()
urls.py
urls.pyは、先にまとめて載せておきます。(実際はビューを追加するたびに行を追加する)
記事の内容に沿って、順を追ってクラスベースビューを実装していく場合は、該当する行を順次追加していって下さい。
from django.urls import path
from . import views
urlpatterns = [
path('create/', views.MemberCreateView.as_view(), name='create'),
path('list/', views.MemberListView.as_view(), name='list'),
path('<int:pk>/update/', views.MemberUpdateView.as_view(), name='update'),
path('<int:pk>/delete/', views.MemberDeleteView.as_view(), name='delete'),
]
views.py
前回実装したCreateView、ListViewです。
今回はUpdateView、DeleteViewを実装していきますが、このviews.pyに追加する形で実装します。
from django.urls import reverse_lazy
from django.views.generic.edit import CreateView
from django.views.generic.list import ListView
from .models import Member
class MemberCreateView(CreateView):
model = Member
fields = "__all__"
success_url = reverse_lazy('list')
class MemberListView(ListView):
model = Member
UpdateViewの使い方
前回は、CreateViewを使ってデータの登録画面、ListViewを使ってデータの一覧画面を実装しました。
このままでは、「誤ったデータを登録した」、「データの内容が変わった」といった場合に、データを修正することができません。
そこで、一覧画面からデータの更新(修正)が行えるような更新画面をUpdateViewを使って実装します。
UpdateViewとは
UpdateViewは登録済みデータの更新(修正)機能に特化したクラスベースビューです。
修正したいデータに対して、更新するためのフォームを表示させることができます。
UpdateViewの使い方
UpdateViewも特にメソッド定義は不要で、いくつかのクラス変数(属性)の設定だけで使えます。
from django.views.generic.edit import UpdateView
class MemberUpdateView(UpdateView):
model = Member
fields = ('name', 'age')
template_name_suffix = '_update_form'
success_url = reverse_lazy('list')
出てくるクラス変数はすべてCreateViewのときに説明済みですが、改めてまとめておきます。
クラス変数 | 内容 |
---|---|
model | データを登録する対象のモデル名 |
fields | データを登録するフィールドの一覧 (”__all__”を指定するとすべてのフィールドが対象) |
template_name_suffix | 使用するテンプレートHTMLファイルの末尾 |
success_url | ポスト成功時のリダイレクト先 |
CreateViewのときも出ましたが、template_name_suffixは、「{モデル名}{template_name_suffix}.html」というファイルをテンプレートとして使用することを指定します。
デフォルトではtemplate_name_suffix="_form"
となっていますが、そのままだとテンプレートファイル名が{モデル名}_form.html
となり、CreateViewのファイル名と同じになってしまうためここでは別のサフィックスを指定しました。
UpdateViewのテンプレートはmember_update_form.html
となるようにしています。
ちなみに、上記のように特にメソッドをオーバーライドする必要がない場合は、views.pyでクラスを定義しなくてもurls.pyで直接UpdateViewを生成することが可能です。
from django.views.generic.edit import UpdateView
from .models import Member
from django.urls import reverse_lazy
urlpatterns = [
...
# urls.pyで直接UpdateViewを指定する
# path('<int:pk>/update/', views.MemberUpdateView.as_view(), name='update'),
path('<int:pk>/update/', UpdateView.as_view(
model=Member,
fields="__all__",
template_name_suffix='_update_form',
success_url=reverse_lazy('list'),
), name='update'),
...
]
この場合は、as_view()メソッドの引数に、必要な属性(modelやfieldsなど)をキーワード引数として渡します。
これで、views.pyでUpdateViewを継承したクラスを定義することとまったく同じことが可能です。
ちなみに上記では、fileds=”__all__”の例(すべてのフィールドが対象)を載せています。
ただし、今後メソッドを追加するなどの拡張が生じたときに結局クラスを定義する必要があるので、はじめから分けておくのがおすすめです。
テンプレート
UpdateViewのテンプレートは以下のようにします。
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="更新">
</form>
UpdateViewのコンテキストとしては、変数formに更新用のフォームが格納されます。
更新用のフォームを入力後、「更新」ボタンを押すことでデータのPOSTメソッドが実行されるような仕組みです。
また、データの一覧画面で、データごとに「更新ボタン」を表示させるために、ListViewで使用したmember_list.htmlを修正します。
<h1>Members</h1>
<ul>
{% for member in object_list %}
<li>
{{ member.name }} - {{ member.age }}
<button onclick="location.href='{% url 'update' member.pk %}'">更新</button> <!-- 更新ページへリンクするボタンを追加 -->
</li>
{% empty %}
<li>データがありません</li>
{% endfor %}
</ul>
<button onclick="location.href='{% url 'update' member.pk %}'">
では、そのデータの更新用ページへのリンクするボタンを追加しています。onclick="location.href='{% url 'update' member.pk %}'"
では、ボタン押下時に遷移するURLを記載しています。
{% url ‘update’ member.pk %}のように、{% url ‘[urls.pyで指定したname]’ [urlsに渡す変数] %}という形式で、urls.pyのnameのURLに変数を埋め込むことが可能です。
今回はurls.pyでupdate用ページのURLを'<int:pk>/update/’としているので、このURL変数の<int:pk>の部分に、member.pkが入ります。
ちなみに、member.pkはMemberモデルのプライマリーキーのことで、データごとに一意に決まるカラム(すべてのデータで重複が許されないカラム)を表します。
自分でプライマリーキーを指定しなければ、Djangoが自動で追加してくれます。(データごとに自動インクリメントされる整数として設定されますが、ユーザには見えません)
ブラウザ表示
まず、一覧画面は以下のように更新ボタンが追加されます。
試しに、一番上のデータの更新ボタンを押します。
上のように、現在の値がすでに入ったフォームが表示されます。
また、URLを見ると、たしかに/{整数}/update/
にアクセスしていることがわかります。(私は何度かデータを追加・削除したので9という中途半端な数字になっています)
では、データの内容を適当に書き換えて、更新ボタンを押してみましょう。
すると、一覧画面に遷移し、データが更新されていることがわかります。(success_urlで一覧画面に遷移するようにしたためです)
DeleteViewの使い方
DeleteViewとは
UpdateViewのおかげで間違えたデータを編集できるようになりました。
もういらなくなったデータを削除する機能も欲しいですね。
そこで、DeleteViewの登場です。
DeleteViewはデータの削除と、削除するときの確認画面を提供してくれます。
DeleteViewの使い方
views.py
DeleteViewもモデルと、遷移先ページを設定するだけでOKです。
from django.views.generic.edit import DeleteView
class MemberDeleteView(DeleteView):
model = Member
success_url = reverse_lazy('list')
テンプレート
DeleteViewではtemplate_name_suffixが”_confirm_delete”なので、ファイル名はmember_confirm_delete.htmlとします。
<form method="post">
{% csrf_token %}
<p>データ "{{ object }}" を本当に削除しますか?</p>
<input type="submit" value="確定">
</form>
DeleteViewでは、object
というコンテキストに、モデルのデータが入ります。
一覧画面にも、削除ボタンを追加しましょう。
更新ボタンとほぼ同じです。
<h1>Members</h1>
<ul>
{% for member in object_list %}
<li>
{{ member.name }} - {{ member.age }}
<button onclick="location.href='{% url 'update' member.pk %}'">更新</button>
<button onclick="location.href='{% url 'delete' member.pk %}'">削除</button>
</li>
{% empty %}
<li>データがありません</li>
{% endfor %}
</ul>
ブラウザ表示
一覧画面に削除ボタンが追加され、削除ボタンを押すと確認画面に遷移します。
データ名が”Member object(9)”のようになっていて、どのデータを削除しようとしているか分からないのが気になります。
ここにMember.nameが表示されるように、models.pyを少し修正します。
from django.db import models
class Member(models.Model):
name = models.CharField(max_length=100)
age = models.IntegerField()
def __str__(self):
return self.name
__str__
メソッドを定義していますが、これはモデルのデータを表示するときの文字列を設定します。
今回は、self.nameとすることで、nameを表示することができるようになります。
これで、もう一度データの削除を試してみましょう。
これで、どのデータを削除しようとしているのかが一目瞭然ですね。
まとめ
今回はデータ更新のUpdateView、データ削除のDeleteViewを実装しました。
前回の記事と合わせると、これでCRUDすべてが使えるようになったわけです。
これだけ使えれば、djangoのデータ登録関連は網羅できるでしょう。
さらに、それぞれのクラスベースビューでは変数の設定だけで機能実現ができたので、覚えるのも簡単です。
なお、侍テラコヤという学習サイトでは、DjangoをはじめPythonやHTML/CSS/JavaScriptを無料で学ぶことができます!
メールアドレスだけで簡単に無料登録できるのでぜひ覗いてみてくださいね。
\無料プランを無期限で試す/
メールアドレスだけで10秒で登録!
Djangoはまだまだたくさんの機能が盛り沢山です。
このサイトでは、他にもさまざまな解説記事を載せているので、ぜひ参考にしてください!
また、独学だけでなく、人から教えてもらうというのも大切です。
以下の記事ではDjangoが学べるプログラミングスクールを、目的別におすすめを紹介していますので、こちらもぜひご検討ください。
コメント