
【第5回】Djangoで日記アプリを作ろう ~編集画面・削除画面編~
2021.12.20
【第5回】Djangoで日記アプリを作ろう ~編集画面・削除画面編~
前回は、ListView と DetailView を利用して、日記の一覧画面と詳細画面を作成しました。
今回は、投稿した日記を編集する画面と、日記の削除を実行する画面を作りましょう!
上記機能の作成を通して、以下の内容を新しく学んでいきます。
- UpdateView を用いた編集画面の実装方法
- DeleteView を用いた削除画面の実装方法
それでは早速、編集画面から作っていきましょう!
UpdateViewを用いた編集画面の作成
ではまず、日記の編集画面を作成していきましょう。
Django が提供する UpdateView を利用すると、編集画面に対応するビューは簡単に実装できます。
ただ今回は、少しオリジナルの UpdateView に、工夫を施してみます。
ユーザーからの入力が正常値であった場合、日記オブジェクトが持つ updated_at フィールドに、編集時の時刻を代入してデータベースに保存してみます。
これは、UpdateView が持つ form_valid メソッドを、オーバーライドすることで実現できます。
UpdateViewを使ってビューを実装
では、UpdateView を用いて、編集画面に対応するビューを実装しましょう。
diary ディレクトリの views.py に、下記のコードを追加しましょう!
このとき、djando.views.generic モジュールから、UpdateView を import して下さい。
1 2 3 4 5 6 7 8 9 10 11 | class DiaryUpdateView(UpdateView): template_name = 'diary_update.html' model = Diary fields = ('date', 'title', 'text',) success_url = reverse_lazy('diary:diary_list') def form_valid(self, form): diary = form.save(commit=False) diary.updated_at = timezone.now() diary.save() return super().form_valid(form) |
編集画面に対応するテンプレートは、diary_update.html としました(後ほど作成しましょう)。
ポイント1:「model」と「fields」
今回追加した、DiaryUpdateView のポイントは大きく2つ。
まず1つ目は、「model」と「fields」というフィールドです。
これにより、diary_update.html の中で、
- date
- title
- text
という、3つのフィールドを持った、diary フォームオブジェクトを利用することができます。
このフォームを通して、ユーザーから日記データ書き換え用のデータを受け取るわけですね!
ポイント2:form_valid メソッド
2つ目のポイントが、form_valid メソッドです。
ユーザーから受け取ったフォーム値は、fields 変数の定義に従って、自動的にバリデーションを受けます。
バリデーションを通過し型や、データ長などに違反がなければ、form_valid 呼び出される仕様です。
このメソッドの中では、まず form.save(commit=False) というコードにより、日記データに対応したフォームオブジェクトを入手します。
フォームオブジェクトが持つ save メソッドは、データベースにデータを保存するメソッドです。
ですが、 commit = False という引数により、データベースには保存処理がされません。
フォームオブジェクトを入手した後、updated_at フィールドに、現在時刻 timezone.now() を代入します。
最後に、 diary.save() により、データベースに保存処理を実行しているわけです。
テンプレートの作成
「diary_update.html」を、templates ディレクトリの中に作成し、下記のようなテンプレートを作成しましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>日記の編集</h1> <form method="post"> {% csrf_token %} {{ form.as_p }} <input type="submit" value="保存"> </form> </body> </html> |
{{ form.as_p }} により、diary フォームオブジェクトが持つ「date」「titile」「text」フィールドが、p タグで囲まれたフォームとしてテンプレートに埋め込まれます。
urls.pyで設定
続いて、urls.py の編集を行います。
diary ディレクトリ内の urls.py に、DiaryUpdateView に対応する、url の設定を行いましょう!
1 2 3 4 5 6 7 8 9 10 11 12 | from django.urls import path from . import views app_name = 'diary' urlpatterns = [ path('index/', views.IndexView.as_view(), name='index'), path('diary/create/', views.DiaryCreateView.as_view(), name='diary_create'), path('diary/create/complete/', views.DiaryCreateCompleteView.as_view(), name='diary_create_complete'), path('diary/list/', views.DiaryListView.as_view(), name='diary_list'), path('diary/detail/<uuid:pk>/', views.DiaryDetailView.as_view(), name='diary_detail'), path('diary/update/<uuid:pk>/', views.DiaryUpdateView.as_view(), name='diary_update'), #追記 ] |
詳細画面の作成と同じで、編集したい日記データの id を受けるために、<uuid:pk>を url の中に仕込んでおきます。
最後に、編集画面へのリンクを、日記の詳細画面の中に追加しましょう。
diary_update.htmlを編集
diary_detail.html を、下記のように編集します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>日記の詳細</h1> <p>{{ diary.date }}</p> <p>{{ diary.title }}</p> <p>{{ diary.text }}</p> <a href="{% url 'diary:diary_update' diary.pk %}">編集</a> <!-- 追加 --> <a href="{% url 'diary:index' %}">戻る</a> </body> </html> |
a タグの href に与える url の中に、 diary.pk を記述するのをお忘れなく!
編集画面の動作確認
ここまで実装できたら、一度プロジェクトを立ち上げて、編集画面が上手く動作するか確かめてみましょう!
日記の詳細画面に「編集」リンクが追加され、編集画面は以下のようになるはずです。

CreateView を利用した場合とは違い、フォームの初期値には、元の日記データの値が入っています。
DeleteViewを用いた削除画面の作成
続いて、DeleteView を用いて、削除画面を作成しましょう。
以下のコードを、diary アプリの views.py に追記しましょう。
DeleteView の import をお忘れなく!
1 2 3 4 | class DiaryDeleteView(DeleteView): template_name = 'diary_delete.html' model = Diary success_url = reverse_lazy('diary:diary_list') |
DeleteView を継承していますが、これまで利用してきた View クラスと、利用方法は大きく変わりません。
template_name フィールドに対応するテンプレートを設定し、削除するデータに対応するモデルを、model フィールドに与えます。
削除確定ボタンを押した後は、一覧画面(diary_list)に遷移するように設定しましょう。
削除画面のビューは、自体は上記コードだけで実現します。
今回は、この DeleteView クラスが持つ、データ削除メソッドをザッと見てみましょう。
DeletionMixinクラスのdeleteメソッド
DeleteView クラスは、数多くのクラスを継承して成り立っています。
そして、その内の一つ DeletionMixin クラスが、実際のデータ削除に関する機能を担っています。
以下のコードは、DeletionMixin クラスが持つ、delete メソッドです。
1 2 3 4 5 6 7 8 9 | def delete(self, request, *args, **kwargs): """ Call the delete() method on the fetched object and then redirect to the success URL. """ self.object = self.get_object() success_url = self.get_success_url() self.object.delete() return HttpResponseRedirect(success_url) |
このメソッドが指定した、データの削除を実行します。
このコードの中身は、かなりシンプル。
削除対象のオブジェクト(日記データ)を入手した後、そのオブジェクトが持つ delete メソッドを呼び出し、データベースから削除しています。
削除後は、return 処理として、success_url に指定された画面にリダイレクトします。
今回の連載では、削除命令が下るとデータベースから、完全にデータが削除される仕様となっています。
もし論理削除したい場合には、DeleteView の delete メソッドをオーバーライドして、その中でロジックを記述すればOKです。
テンプレートの作成
それでは、次の工程を進めていきましょう!
- DiaryDeleteView に対応するテンプレートの作成
- urls.py の設定
- 日記の詳細画面に削除画面へのリンク貼り
まずは、テンプレート作成からです。
削除画面に対応するテンプレートを「diary_detele.html」とし、以下のように記述しましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>日記の削除</h1> <form method="post"> {% csrf_token %} <p>{{ diary.date }} {{ diary.title }} を削除します</p> <input type="submit" value="削除"> </form> </body> </html> |
DeleteView を使用した場合、削除対象のデータがテンプレート内部で利用できるように、自動で処理がなされます。
urls.pyで設定
続いて、urls.py を以下のように編集しましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 | from django.urls import path from . import views app_name = 'diary' urlpatterns = [ path('index/', views.IndexView.as_view(), name='index'), path('diary/create/', views.DiaryCreateView.as_view(), name='diary_create'), path('diary/create/complete/', views.DiaryCreateCompleteView.as_view(), name='diary_create_complete'), path('diary/list/', views.DiaryListView.as_view(), name='diary_list'), path('diary/detail/<uuid:pk>/', views.DiaryDetailView.as_view(), name='diary_detail'), path('diary/update/<uuid:pk>/', views.DiaryUpdateView.as_view(), name='diary_update'), path('diary/delete/<uuid:pk>/', views.DiaryDeleteView.as_view(), name='diary_delete'), #追加 ] |
削除対象の日記データの id を指定するために、url の中に<uuid:pk>を記述するのをお忘れなく!
リンクの貼り付け
最後に、diary_detail.html を以下のように編集し、削除画面へのリンクを貼りましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>日記の詳細</h1> <p>{{ diary.date }}</p> <p>{{ diary.title }}</p> <p>{{ diary.text }}</p> <a href="{% url 'diary:diary_update' diary.pk %}">編集</a> <a href="{% url 'diary:diary_delete' diary.pk %}">削除</a> <!-- 追加 --> <a href="{% url 'diary:index' %}">戻る</a> </body> </html> |
削除画面の動作確認
ここまで実装が完了したら、Django プロジェクトを立ち上げて、機能を確認しましょう。
日記の詳細画面にある、削除画面へのリンクを辿ると、以下のような画面が表示されるはずです。

削除ボタンを押すと、削除が実行され、日記一覧画面に遷移します。
また、Django 管理サイトにアクセスすると、日記データが削除されていることが確認できます。
第6回へつづく!
今回の記事では、日記の編集画面と削除画面を実装しました。
今回の記事のポイントは、以下の2つです。
- 編集画面の作成では UpdateView が便利
- 削除画面の作成では DeleteView が便利
次回は、Django テンプレート言語について学び、アプリの画面デザインを少し整えましょう。
それでは、次回もお楽しみに!
第6回はこちら!
こちらの記事もオススメ!
書いた人はこんな人

- 「好きを仕事にするエンジニア集団」の(株)ライトコードです!
ライトコードは、福岡、東京、大阪の3拠点で事業展開するIT企業です。
現在は、国内を代表する大手IT企業を取引先にもち、ITシステムの受託事業が中心。
いずれも直取引で、月間PV数1億を超えるWebサービスのシステム開発・運営、インフラの構築・運用に携わっています。
システム開発依頼・お見積もり大歓迎!
また、現在「WEBエンジニア」「モバイルエンジニア」「営業」「WEBデザイナー」「WEBディレクター」を積極採用中です!
インターンや新卒採用も行っております。
以下よりご応募をお待ちしております!
https://rightcode.co.jp/recruit
ITエンタメ10月 13, 2023Netflixの成功はレコメンドエンジン?
ライトコードの日常8月 30, 2023退職者の最終出社日に密着してみた!
ITエンタメ8月 3, 2023世界初の量産型ポータブルコンピュータを開発したのに倒産!?アダム・オズボーン
ITエンタメ7月 14, 2023【クリス・ワンストラス】GitHubが出来るまでとソフトウェアの未来