ここではコメントの編集・更新機能を実装しますが,コメントの投稿者だけが操作できるという機能も付け加えます.具体的には最初に開発したユーザ認証機能のないコメント掲示板の更新コードに,投稿者であるかどうかを判断するコードを追加します.
comments/views.py
def 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...
自身のコメントを編集します.
自身のコメントは更新できました.
URLを細工して他ユーザの編集ページを開こうとしても一覧ページへリダイレクトされます.
なお,編集フォームを細工して不正な更新を行おうとした場合は 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 行目のチェックで不正を防止できます.次のページでは削除機能を実装しよう.