• トップ
  • ブログ一覧
  • 【第5回】Djangoで日記アプリを作ろう ~編集画面・削除画面編~
  • 【第5回】Djangoで日記アプリを作ろう ~編集画面・削除画面編~

    広告メディア事業部広告メディア事業部
    2021.06.07

    エンジニアになろう!

    【第5回】Djangoで日記アプリを作ろう ~編集画面・削除画面編~

    前回は、ListView と DetailView を利用して、日記の一覧画面と詳細画面を作成しました。

    【第4回】Djangoで日記アプリを作ろう ~一覧画面・詳細画面編~2021.05.31【第4回】Djangoで日記アプリを作ろう ~一覧画面・詳細画面編~【第4回】Djangoで日記アプリを作ろう ~一覧画面・詳細画面編~前回は、Model と ModelForm を利用...

    今回は、投稿した日記を編集する画面と、日記の削除を実行する画面を作りましょう!

    上記機能の作成を通して、以下の内容を新しく学んでいきます。

    1. UpdateView を用いた編集画面の実装方法
    2. 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 の中で、

    1. date
    2. title
    3. 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です。

    テンプレートの作成

    それでは、次の工程を進めていきましょう!

    1. DiaryDeleteView に対応するテンプレートの作成
    2. urls.py の設定
    3. 日記の詳細画面に削除画面へのリンク貼り

    まずは、テンプレート作成からです。

    削除画面に対応するテンプレートを「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つです。

    1. 編集画面の作成では UpdateView が便利
    2. 削除画面の作成では DeleteView が便利

    次回は、Django テンプレート言語について学び、アプリの画面デザインを少し整えましょう。

    それでは、次回もお楽しみに!

    第6回はこちら!

    【第6回】Djangoで日記アプリを作ろう ~Djangoテンプレート言語編~2021.06.14【第6回】Djangoで日記アプリを作ろう ~Djangoテンプレート言語編~【第6回】Djangoで日記アプリを作ろう ~Djangoテンプレート言語編~前回は、UpdateView と Del...

    こちらの記事もオススメ!

    featureImg2020.07.17ライトコード的「やってみた!」シリーズ「やってみた!」を集めました!(株)ライトコードが今まで作ってきた「やってみた!」記事を集めてみました!※作成日が新し...
    featureImg2020.07.30Python 特集実装編※最新記事順Responder + Firestore でモダンかつサーバーレスなブログシステムを作ってみた!P...

    ライトコードでは、エンジニアを積極採用中!

    ライトコードでは、エンジニアを積極採用しています!社長と一杯しながらお話しする機会もご用意しております。そのほかカジュアル面談等もございますので、くわしくは採用情報をご確認ください。

    採用情報へ

    広告メディア事業部

    広告メディア事業部

    おすすめ記事

    エンジニア大募集中!

    ライトコードでは、エンジニアを積極採用中です。

    特に、WEBエンジニアとモバイルエンジニアは是非ご応募お待ちしております!

    また、フリーランスエンジニア様も大募集中です。

    background