Python Django 入門トップページ


ユーザ認証とコメント掲示板の開発

  1. プロジェクトの概要
  2. プロジェクトの作成と初期設定
  3. アプリケーションの作成と有効化
  4. ルートの記述
  5. ビューの定義
  6. HTML のテンプレート化
  7. HTML ファイルの作成
  8. Web ページ雛形の表示確認
  9. トップページの作成
  10. データベースのマイグレーション
  11. ユーザの作成
  12. ユーザ認証機能の実装
  13. セッション情報の確認
  14. ユーザ認証の状態を表示
  15. Navbar を設置
  16. モデルの作成とマイグレーション
  17. テストデータの投入
  18. コメントの一覧表示
  19. ページネーションと更新逆順表示
  20. コメント投稿機能の実装
  21. フラッシュメッセージ
  22. コメント詳細表示ページの実装
  23. 投稿者のユーザ名とメールアドレスの表示
  24. 投稿者であるかどうかの判断
  25. 編集・更新機能の実装
  26. コメント削除機能の実装
  27. Navbar の調整
  28. Profile の表示
  29. Profile の編集と更新
  30. パスワードの変更
  31. 管理サイトの準備
  32. 管理ユーザの登録
  33. 管理サイトへのログインとスタッフの登録
  34. グループの追加と権限の付与
  35. 管理サイトに comments アプリケーションを登録
  36. Comments アプリケーションから管理サイトへ

ユーザ認証とコメント掲示板の開発

編集・更新機能の実装

ここではコメントの編集・更新機能を実装しますが,コメントの投稿者だけが操作できるという機能も付け加えます.具体的には最初に開発したユーザ認証機能のないコメント掲示板の更新コードに,投稿者であるかどうかを判断するコードを追加します.

comments/views.pydef comments_update(request, comment_id):
    if not request.user.is_authenticated:
        return redirect('%s?next=%s' % (settings.LOGIN_URL, request.path))
    # context = {}
    # context['page_title'] = 'コメントの編集'
    # return render(request, 'comments/form.html', context)
    if request.method == 'POST':
        form = CommentForm(request.POST)
        if form.is_valid():
            comment = get_object_or_404(Comment, pk=comment_id)
            if comment.is_owner(request.user) == False:
                messages.success(request, '他ユーザのコメントは編集できません')
                return redirect(reverse('comments:index'))
            comment.title = form.cleaned_data.get("title")
            comment.body = form.cleaned_data.get("body")
            comment.save()
            messages.success(request, '更新しました')
            return redirect(reverse('comments:index'))
        else:
            # エラーメッセージをつけて返す
            context = {}
            context['page_title'] = 'コメントの編集'
            context['form_name'] = 'コメントの編集'
            context['button_label'] = 'コメントを更新する'
            context['form'] = form
            return render(request, 'comments/form.html', context)
    else:
        context = {}
        comment = get_object_or_404(Comment, pk=comment_id)
        if comment.is_owner(request.user) == False:
            messages.success(request, '他ユーザのコメントは編集できません')
            return redirect(reverse('comments:index'))
        context['form'] = CommentForm(
                            initial={
                                'title' : comment.title,
                                'body' : comment.body,
                            }
                        )
        context['page_title'] = 'コメントの編集'
        context['form_name'] = 'コメントの編集'
        context['button_label'] = 'コメントを更新する'
        return render(request, 'comments/form.html', context)

Web サーバを起動してコメントの編集を行ってみます.

(py39) C:\Users\lecture\Documents\django\django_comment_auth>python manage.py runserver ⏎
Watching for file changes with StatReloader
Performing system checks...

自身のコメントを編集します.

django2022-00104

自身のコメントは更新できました.

django2022-00105

URLを細工して他ユーザの編集ページを開こうとしても一覧ページへリダイレクトされます.

django2022-00106

なお,編集フォームを細工して不正な更新を行おうとした場合は CSRF (Cross-Site Request Forgery) トークンの不一致でエラーになるはずです.これは,form.html の中に設置した {% csrf_token %} によって実現されています.

comments/templates/comments/show.html(抜粋)<h1 class="my-5">{{ form_name }}</h1>
<form method="POST">
  {% csrf_token %}
  {{ form.as_p }}
  <button type="submit" class="btn btn-primary">{{ button_label }}</button>
</form>

編集画面の HTML ソースを表示すると,CSRF トークンが仕込まれていることがわかります.

生成されたHTMLソース<form method="POST">
    <input type="hidden" name="csrfmiddlewaretoken" value="Y2wWTgAbpZJDOIvFbUIROwa5m6BbLuJPRZvKDNV15yND2SHt5IV5PUJgOrD5xazP">
    <p>
        <label for="id_title">タイトル:</label>
        <input type="text" name="title" value="user_a" class="form-control" maxlength="200" required id="id_title">
    </p>
    <p>
        <label for="id_body">本文:</label>
        <input type="text" name="body" value="User Aが投稿します" class="form-control" maxlength="1000" required id="id_body">
    </p>
    <button type="submit" class="btn btn-primary">コメントを更新する</button>
</form>

万が一 CSRF トークンのチェックを通過しても,views.py の 11〜13 行目のチェックで不正を防止できます.次のページでは削除機能を実装しよう.

目次に戻る