【第5回】Djangoで日記アプリを作ろう ~編集画面・削除画面編~
エンジニアになろう!
【第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 して下さい。
1class DiaryUpdateView(UpdateView):
2 template_name = 'diary_update.html'
3 model = Diary
4 fields = ('date', 'title', 'text',)
5 success_url = reverse_lazy('diary:diary_list')
6
7 def form_valid(self, form):
8 diary = form.save(commit=False)
9 diary.updated_at = timezone.now()
10 diary.save()
11 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<!DOCTYPE html>
2<html lang="en">
3<head>
4 <meta charset="UTF-8">
5 <title>Title</title>
6</head>
7<body>
8<h1>日記の編集</h1>
9<form method="post">
10 {% csrf_token %}
11 {{ form.as_p }}
12 <input type="submit" value="保存">
13</form>
14</body>
15</html>
{{ form.as_p }} により、diary フォームオブジェクトが持つ「date」「titile」「text」フィールドが、p タグで囲まれたフォームとしてテンプレートに埋め込まれます。
urls.pyで設定
続いて、urls.py の編集を行います。
diary ディレクトリ内の urls.py に、DiaryUpdateView に対応する、url の設定を行いましょう!
1from django.urls import path
2from . import views
3
4app_name = 'diary'
5urlpatterns = [
6 path('index/', views.IndexView.as_view(), name='index'),
7 path('diary/create/', views.DiaryCreateView.as_view(), name='diary_create'),
8 path('diary/create/complete/', views.DiaryCreateCompleteView.as_view(), name='diary_create_complete'),
9 path('diary/list/', views.DiaryListView.as_view(), name='diary_list'),
10 path('diary/detail/<uuid:pk>/', views.DiaryDetailView.as_view(), name='diary_detail'),
11 path('diary/update/<uuid:pk>/', views.DiaryUpdateView.as_view(), name='diary_update'), #追記
12]
詳細画面の作成と同じで、編集したい日記データの id を受けるために、<uuid:pk>を url の中に仕込んでおきます。
最後に、編集画面へのリンクを、日記の詳細画面の中に追加しましょう。
diary_update.htmlを編集
diary_detail.html を、下記のように編集します。
1<!DOCTYPE html>
2<html lang="en">
3<head>
4 <meta charset="UTF-8">
5 <title>Title</title>
6</head>
7<body>
8<h1>日記の詳細</h1>
9<p>{{ diary.date }}</p>
10<p>{{ diary.title }}</p>
11<p>{{ diary.text }}</p>
12<a href="{% url 'diary:diary_update' diary.pk %}">編集</a> <!-- 追加 -->
13<a href="{% url 'diary:index' %}">戻る</a>
14</body>
15</html>
a タグの href に与える url の中に、 diary.pk を記述するのをお忘れなく!
編集画面の動作確認
ここまで実装できたら、一度プロジェクトを立ち上げて、編集画面が上手く動作するか確かめてみましょう!
日記の詳細画面に「編集」リンクが追加され、編集画面は以下のようになるはずです。
CreateView を利用した場合とは違い、フォームの初期値には、元の日記データの値が入っています。
DeleteViewを用いた削除画面の作成
続いて、DeleteView を用いて、削除画面を作成しましょう。
以下のコードを、diary アプリの views.py に追記しましょう。
DeleteView の import をお忘れなく!
1class DiaryDeleteView(DeleteView):
2 template_name = 'diary_delete.html'
3 model = Diary
4 success_url = reverse_lazy('diary:diary_list')
DeleteView を継承していますが、これまで利用してきた View クラスと、利用方法は大きく変わりません。
template_name フィールドに対応するテンプレートを設定し、削除するデータに対応するモデルを、model フィールドに与えます。
削除確定ボタンを押した後は、一覧画面(diary_list)に遷移するように設定しましょう。
削除画面のビューは、自体は上記コードだけで実現します。
今回は、この DeleteView クラスが持つ、データ削除メソッドをザッと見てみましょう。
DeletionMixinクラスのdeleteメソッド
DeleteView クラスは、数多くのクラスを継承して成り立っています。
そして、その内の一つ DeletionMixin クラスが、実際のデータ削除に関する機能を担っています。
以下のコードは、DeletionMixin クラスが持つ、delete メソッドです。
1def delete(self, request, *args, **kwargs):
2 """
3 Call the delete() method on the fetched object and then redirect to the
4 success URL.
5 """
6 self.object = self.get_object()
7 success_url = self.get_success_url()
8 self.object.delete()
9 return HttpResponseRedirect(success_url)
このメソッドが指定した、データの削除を実行します。
このコードの中身は、かなりシンプル。
削除対象のオブジェクト(日記データ)を入手した後、そのオブジェクトが持つ delete メソッドを呼び出し、データベースから削除しています。
削除後は、return 処理として、success_url に指定された画面にリダイレクトします。
今回の連載では、削除命令が下るとデータベースから、完全にデータが削除される仕様となっています。
もし論理削除したい場合には、DeleteView の delete メソッドをオーバーライドして、その中でロジックを記述すればOKです。
テンプレートの作成
それでは、次の工程を進めていきましょう!
- DiaryDeleteView に対応するテンプレートの作成
- urls.py の設定
- 日記の詳細画面に削除画面へのリンク貼り
まずは、テンプレート作成からです。
削除画面に対応するテンプレートを「diary_detele.html」とし、以下のように記述しましょう。
1<!DOCTYPE html>
2<html lang="en">
3<head>
4 <meta charset="UTF-8">
5 <title>Title</title>
6</head>
7<body>
8<h1>日記の削除</h1>
9<form method="post">
10 {% csrf_token %}
11 <p>{{ diary.date }} {{ diary.title }} を削除します</p>
12 <input type="submit" value="削除">
13</form>
14</body>
15</html>
DeleteView を使用した場合、削除対象のデータがテンプレート内部で利用できるように、自動で処理がなされます。
urls.pyで設定
続いて、urls.py を以下のように編集しましょう。
1from django.urls import path
2from . import views
3
4app_name = 'diary'
5urlpatterns = [
6 path('index/', views.IndexView.as_view(), name='index'),
7 path('diary/create/', views.DiaryCreateView.as_view(), name='diary_create'),
8 path('diary/create/complete/', views.DiaryCreateCompleteView.as_view(), name='diary_create_complete'),
9 path('diary/list/', views.DiaryListView.as_view(), name='diary_list'),
10 path('diary/detail/<uuid:pk>/', views.DiaryDetailView.as_view(), name='diary_detail'),
11 path('diary/update/<uuid:pk>/', views.DiaryUpdateView.as_view(), name='diary_update'),
12 path('diary/delete/<uuid:pk>/', views.DiaryDeleteView.as_view(), name='diary_delete'), #追加
13]
削除対象の日記データの id を指定するために、url の中に<uuid:pk>を記述するのをお忘れなく!
リンクの貼り付け
最後に、diary_detail.html を以下のように編集し、削除画面へのリンクを貼りましょう。
1<!DOCTYPE html>
2<html lang="en">
3<head>
4 <meta charset="UTF-8">
5 <title>Title</title>
6</head>
7<body>
8<h1>日記の詳細</h1>
9<p>{{ diary.date }}</p>
10<p>{{ diary.title }}</p>
11<p>{{ diary.text }}</p>
12<a href="{% url 'diary:diary_update' diary.pk %}">編集</a>
13<a href="{% url 'diary:diary_delete' diary.pk %}">削除</a> <!-- 追加 -->
14<a href="{% url 'diary:index' %}">戻る</a>
15</body>
16</html>
削除画面の動作確認
ここまで実装が完了したら、Django プロジェクトを立ち上げて、機能を確認しましょう。
日記の詳細画面にある、削除画面へのリンクを辿ると、以下のような画面が表示されるはずです。
削除ボタンを押すと、削除が実行され、日記一覧画面に遷移します。
また、Django 管理サイトにアクセスすると、日記データが削除されていることが確認できます。
第6回へつづく!
今回の記事では、日記の編集画面と削除画面を実装しました。
今回の記事のポイントは、以下の2つです。
- 編集画面の作成では UpdateView が便利
- 削除画面の作成では DeleteView が便利
次回は、Django テンプレート言語について学び、アプリの画面デザインを少し整えましょう。
それでは、次回もお楽しみに!
第6回はこちら!
こちらの記事もオススメ!
2020.07.17ライトコード的「やってみた!」シリーズ「やってみた!」を集めました!(株)ライトコードが今まで作ってきた「やってみた!」記事を集めてみました!※作成日が新し...
2020.07.30Python 特集実装編※最新記事順Responder + Firestore でモダンかつサーバーレスなブログシステムを作ってみた!P...
ライトコードでは、エンジニアを積極採用中!
ライトコードでは、エンジニアを積極採用しています!社長と一杯しながらお話しする機会もご用意しております。そのほかカジュアル面談等もございますので、くわしくは採用情報をご確認ください。
採用情報へ
「好きを仕事にするエンジニア集団」の(株)ライトコードです! ライトコードは、福岡、東京、大阪の3拠点で事業展開するIT企業です。 現在は、国内を代表する大手IT企業を取引先にもち、ITシステムの受託事業が中心。 いずれも直取引で、月間PV数1億を超えるWebサービスのシステム開発・運営、インフラの構築・運用に携わっています。 システム開発依頼・お見積もり大歓迎! また、現在「WEBエンジニア」「モバイルエンジニア」「営業」「WEBデザイナー」「WEBディレクター」を積極採用中です! インターンや新卒採用も行っております。 以下よりご応募をお待ちしております! https://rightcode.co.jp/recruit