Djangoで始めるブログ作成講座③:コメント投稿機能を導入しよう!

「Djangoで始めるブログ作成講座」の第三回です。
前回はDjangoで画像を扱い、ブログのアイキャッチ画像を定義しました。

関連記事

「Djangoで始めるブログ作成講座」の第二回です。 前回はブログの基本的な内容を実装するにとどまりました。 [sitecard subtitle=関連記事 url=https://freemas.stepupkaraoke.com[…]

IMG

今回は投稿の詳細画面に誰でもコメントを投稿できる機能を実装していきましょう!
完成形のイメージは下記のようになります。

この記事を読んで取り組むことで、Djangoの以下の基本的な使い方を習得することができます。

  • DjangoでのModelの結合の仕方
  • 結合先のデータ削除の場合の挙動
  • 同一ViewでのPost時のふるまいの指定
  • commit=Falseでのデータ保存
  • Django管理画面でのinlineの使い方
  • Django管理画面で、データ一覧画面の表示のカスタマイズ

今回はDjangoの多くのことが学べる回となっています。
その分Djangoの便利な部分も多数出てきますので、楽しく作りながら学んでいきましょう!

Djangoで始めるブログ作成講座③:コメント投稿機能を導入しよう!

今回は

  • コメント投稿フォームの設置
  • コメント投稿機能実装
  • コメントの管理画面実装

の3段階で実装していきます。まずはコメントフォームの設置からです。

コメント投稿フォームの設置:Model作成

新たにmodels.pyに追記します。

models.py
コメントの項目は以下の通りにしています。

  • Post:どの投稿にコメントをしたかを外部結合で指定
  • author:コメントをした人の名前
  • text:コメントの本文
  • created_at:コメントの投稿日時
  • approved_comment:許可されたコメントか否か

表でユーザーに入力してもらうのはauthoerとtextのみになります。

post

on_detele=models.CASCADEは紐づいている別テーブルのデータが削除されたら、このデータも削除することを表します。
今回の場合は紐づいているPost、つまり投稿が削除された段階で紐づくコメントも削除するようにしています。

他にもいくつか種類があり、例えば以下はそれぞれ結合先データ削除時に異なる動きを見せます。

  • on_delete=models.SET_NULL:カラムを空に
  • on_delete=models.DEFAULT:Modelで指定した初期値に

データによって、どの値に戻したいのか、そもそもデータを丸ごと削除したいのかは変わってくるので、よく検討するようにしましょう。

コメント投稿フォームの設置:Views作成

views.py
新たにコンテキストに追加する形を取っています。
追加しているのはコメントの全件、およびコメント投稿フォームです。

コメントの全件は投稿に紐づくコメントのみを取得しています。
またこれに紐づくCommentFormクラスを持つforms.pyも作成しましょう。

forms.py
forms.pyはCommentのModelのうち、名前と本文を入力させるフィールドを表示させるシンプルなものです。

コメント投稿フォームの設置:Template作成

続いてテンプレートの方にも修正を加えます。

post_list.html
Commentsという欄にコメントの一覧とコメントフォームを追加しています。

未承認コメントは隠す

分岐により、管理者が承認していないコメントは「承認待ち」だと表示するようにしています。
データはViewが取得してくれるので、テンプレート側で捌くだけで済みます。

コメント投稿フォーム

フォームはHTMLのp要素でマークアップしています。
csrf_tokenはフォームお決まりのセキュリティ対策ですね。

さて、実装が終ったところで開発環境にアクセスしてブログの記事詳細画面を見てみましょう。
下側に下記画像のようにコメントフォームが出ていれば成功です。

ただ、もちろんコメントを送ってもデータベースには反映されません。
反映させるための処理を、続いて記載していきましょう。

コメント投稿機能実装:Viewに追記する

先ほど修正したPostDetailViewに追記しましょう。

フォームの入力値に問題がなければ、投稿に紐づけてから登録する

CommentFormで問題がなければ、一旦commit=Falseでsave関数を発行しています。
この段階で保存の準備は整っているのですが、まだ登録はしていません。

その次のcomment.post = self.objectで紐づく投稿を取得しているので、そのために一旦保留していると思ってください。
紐づき投稿が分かった場合は保留する必要がなくなったので、comment.save()でデータベースに保存しています。

このように、保存前にすることがある場合にはcommit=Falseで保留にすることがあるのを覚えておきましょう。

コメント投稿機能実装:コメントが送れるか確認

Viewの修正が終ったところで、コメントが投稿できるかどうか確認してみましょう。
もう一度投稿詳細画面に入り、適当なコメントを打ってみてください。

上記のように、「管理人の承認待ちです」が表示されれば適切にデータベースに保存されています。
次はこのコメントを管理画面で承認してみましょう!

コメントの管理画面実装:詳細画面にコメントを追加

admin.py
投稿詳細管理画面にコメントも追加

一つのModel管理画面で、別のModelを含めることができるDjangoのInlineという機能を用いています。
今回はこれを用いて、投稿の詳細画面に下記のようにコメントを含めました

コメントの承認も出来るので、実際に使うときにかなり便利ですね。
今回のCommentInlineの説明は以下の通りです。

  • model:紐づけるモデルを選択します
  • extras:空のカラムの数を指定します。1を入力すると、上記のコメントの下に新規で空のフォームが追加されます。
  • fields:どの項目を表示するかを指定します。

基本的にはModelの指定と同じなので分かりやすいと思います。
extrasはここだけで登場するので、覚えておくと良いでしょう。

コメント数を測定して、記事一覧画面に反映

このままではどの投稿にコメントが付いているのか分からないので、コメント数を計測して表示します。
ここで定義した関数「get_comment_count」は投稿に紐づくコメント数を取得しています。

obj.Modelで定義したrelated_name.countで取得可能です。
Modelで定義したrelated_nameはもし違う文言を指定しているならばそちらに合わせてください。

COMMENT COUNTが表示されていれば成功しています。

コメントの管理画面実装:コメント一覧を追加

投稿に紐づくコメントが完成しましたが、どうせならコメントを一覧で確認したいですね。
ということで、コメント一覧の管理場面も作成してしまいましょう。

admin.py
先ほど追加したPostAdminクラスの下に追記しましょう。
かなり項目が多いですが、これを実装することで管理画面に以下のようなコメント一覧画面が表示されます。
様々な項目が追加された、ハイスペックな管理画面が出来ています。
コードと実際の管理画面を紐づけながら、見ていきましょう。
フィルターフィールドを追加

管理画面右側のフィルターに表示する項目を指定します。
今回は承認しているかどうか、と、いつ投稿されたコメントか、でコメントを絞り込むことが可能です。

検索フィールドを追加

管理画面上側の検索窓を追加します。
テキストボックスに入力した値を、指定したフィールド名だけで検索、絞り込みを行ってくれます。

今回はコメント本文、投稿名、投稿者の3つから検索してくれます。
投稿名ですが、コメントのように別のモデルクラスと結合している場合は「モデル名__カラム名」で値を取得できます。

真ん中が「_」2つですので、間違えないように気を付けてください。

編集不可フィールドを追加

文字通り、表示されますが編集できない項目を指定します。
今回はコメントの投稿日を指定しているので、各種コメント詳細画面では以下のように指定されます。

投稿日が編集できなくなっているのが分かりますね。

コメントに紐づく投稿名と編集画面へのリンク追加

一覧画面にて、コメント側からも紐づいた先が分かるようにしています。
まずはコメントが紐づく投稿の編集画面を取得してurlに代入しています。

さらにそれを踏まえてHTMLコードを作り出しました。
format_htmlは上記のように「{}」を指定し、その後ろに「{}」の数だけ値を指定します。今回はリンク先URLと紐づいた投稿名を表示しました。

この関数「get_post_link」はそのまま「list_display」に指定可能です。
このように一覧で表示したい内容をお好みで変更することもできます。

おわりに

今回は記述量こそ多いものの、別の言語ではさらに多くのコード記述が必要になります。
比較してみると2/3程度になっていて、このように記述量が少ないのはDjangoの、ひいてはPythonの良い点ですね。

内容も分かりやすく、理解しやすい記述が多くなっていて頭に入りやすいものになっています。
さて、今回もここまでのソースをGithubに掲載しておくので、もしも見返したい場合は確認してみてください。

Githubリンク(BLOGーコメント投稿機能追加)

次の記事では、投稿一覧画面にページング機能を実装していきましょう。

関連記事

「Djangoで始めるブログ作成講座」の第四回です。 前回はブログにコメント投稿機能を実装し、管理画面のカスタマイズも同時に行いましたね。 [sitecard subtitle=関連記事 url=https://freemas.st[…]