次に投稿機能を実装しよう.まず,forms.py にフォームの要素を定義します.それと同時にホワイトスペースの削除と入力内容を検証するための関数も定義します.
comments/forms.py
from django import forms
from .models import Comment
class CommentForm(forms.ModelForm):
class Meta:
model = Comment
fields = ('title', 'body')
widgets = {
'title': forms.TextInput(attrs={
'class': 'form-control'
}),
'body': forms.TextInput(attrs={
'class': 'form-control'
}),
}
labels = {
'title': 'タイトル',
'body': '本文',
}
def clean(self):
data = super().clean()
title = data.get('title')
body = data.get('body')
if title is None:
msg = "タイトルが入力されていません"
self.add_error('title', msg)
elif len(title) > 10:
msg = "タイトルの最大文字数は10文字です"
self.add_error('title', msg)
if body is None:
msg = "本文が入力されていません"
self.add_error('body', msg)
elif len(body) > 20:
msg = "本文の最大文字数は20文字です"
self.add_error('body', msg)
次に,form.html の中に,フォームの要素を配置し forms.py を読み込みます.
comments/templates/comments/form.html
{% extends "base.html" %}
{% block title %}
{{ page_title }}
{% endblock %}
{% block content %}
<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>
<ul>
<li>
<a href="{% url 'comments:index' %}">コメント一覧</a>
</li>
<li>
<a href="{% url 'comments:show' 10 %}">コメント詳細</a>
</li>
<li>
<a href="{% url 'comments:create' %}">コメント投稿</a>
</li>
<li>
<a href="{% url 'comments:update' 10 %}">コメント更新</a>
</li>
<li>
<a href="{% url 'comments:delete' 10 %}">コメント削除</a>
</li>
<li>
<a href="/">トップページへ</a>
</li>
</ul>
{% endblock content %}
views.py には投稿の処理を定義します.
comments/views.py
from django.conf import settings
from django.shortcuts import render
from django.contrib.auth import authenticate, login, logout
from django.shortcuts import redirect
from django.urls import reverse
from .models import Comment
from .forms import CommentForm
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
# Create your views here.
...(中略)...
def comments_create(request):
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 = Comment()
comment.title = form.cleaned_data.get("title")
comment.body = form.cleaned_data.get("body")
comment.owner_id = request.user.id
comment.save()
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 = {}
context['form'] = CommentForm(
initial={
# 'title' : 'title',
}
)
context['page_title'] = 'コメントの投稿'
context['form_name'] = 'コメントの投稿'
context['button_label'] = 'コメントを投稿する'
return render(request, 'comments/form.html', context)
Web サーバを起動し,user_a でログインした状態でコメントを投稿してみる.
(py39) C:\Users\lecture\Documents\django\django_comment_auth>python manage.py runserver ⏎
Watching for file changes with StatReloader
Performing system checks...
コメントの投稿ページを開こうとしたときには GET メソッドが Web サーバにリクエストされることになるので,views.py の 38〜47 行目の処理が実行されます.
上の画面で「コメントを投稿する」ボタンをクリックすると,今度は POST メソッドで Web サーバにリクエストされることになるので,views.py の 21〜36 行目の処理が実行されることになります.投稿できれば次の画面にリダイレクトされます.
投稿されたコメントには投稿者の user_id が owner_id として保存されていること確認しよう.
(py39) C:\Users\lecture\Documents\django\django_comment_auth>sqlite3 db.sqlite3 ⏎ SQLite version 3.38.2 2022-03-26 13:51:10 Enter ".help" for usage hints. sqlite> .headers ON ⏎ sqlite> select * from comments_comment; ⏎ id|title|body|created_at|updated_at|owner_id 1|最初のコメント (a)|コメントの本文|2022-07-27 11:01:00|2022-07-27 11:01:00|1 2|2個目のコメント (b)|コメントの本文2|2022-07-27 11:02:00|2022-07-27 11:02:00|2 3|<3個目>のコメント (a)|<h1>コメントの本文3</h1>|2022-07-27 11:03:00|2022-07-27 11:03:00|1 4|4個目のコメント (b)|コメントの本文4|2022-07-27 11:04:00|2022-07-27 11:04:00|2 5|5個目のコメント (a)|コメントの本文5|2022-07-27 11:05:00|2022-07-27 11:05:00|1 6|6個目のコメント (b)|コメントの本文6|2022-07-27 11:06:00|2022-07-27 11:06:00|2 7|7個目のコメント (a)|コメントの本文7|2022-07-27 11:07:00|2022-07-27 11:07:00|1 8|8個目のコメント (b)|コメントの本文8|2022-07-27 11:08:00|2022-07-27 11:08:00|2 9|9個目のコメント (a)|コメントの本文9|2022-07-27 11:09:00|2022-07-27 11:20:00|1 10|10個目のコメント (b)|コメントの本文10|2022-07-27 11:10:00|2022-07-27 11:10:00|2 11|user_a|User Aが投稿します|2022-07-27 19:15:38.402622|2022-07-27 19:15:38.402622|1 sqlite> .exit ⏎ (py39) C:\Users\lecture\Documents\django\django_comment_auth>
次は投稿完了時にフラッシュメッセージが表示されるようにしよう.