8
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Django2.0でブログの作成(その4:記事へのコメント)

Posted at

その4

記事に対してコメントを表示させましょう。
commentはmodels.pyでDBを持ちますが、コメント入力フォームはforms.pyで作ります。
modelとformの違いはこちら、

Djangoにおけるforms.pyとmodels.pyの違い
modelsはDBに対応するものですが、formsは入力画面に対応するものです。
modelsとformsを連携させたり、modelからformを作ることはありますが、 両者は別の責任を担います。

ふむ。
では早速。

models.py

追加する。

blog/models.py
class Comment(models.Model):
    post = models.ForeignKey('Post', on_delete=models.CASCADE)
    author = models.ForeignKey('auth.User', on_delete=models.CASCADE)
    name = models.CharField(max_length=200)
    text = models.TextField()
    created_date = models.DateTimeField(
            default=timezone.now)

    class Meta:
        ordering = ['-created_date']

'Post', on_delete=models.CASCADEとは、Postが削除された時に、Commentも一緒に削除するということである。

DB更新

python manage.py makemigrations blog
python manage.py migrate blog

forms.py

ないので、新規作成します。
これは、コメント入力フォームからmodels.pyのCommentに繋げています。

blog/forms.py
from django import forms
from . import models

class CommentForm(forms.ModelForm):
    class Meta:
        model = models.Comment
        fields = ('name', 'text',)

views.py

以下のように、def articleの中身を書き換えます。

blog/views.py
()
from .models import Post, Comment #Comment追加
from . import forms #この行追加

()
def article(request, pk):
    article = Post.objects.get(id=pk)
    comments = Comment.objects.filter(post=article)

    if request.method == "POST": #入力フォームはPOSTなので
        form = forms.CommentForm(request.POST)
        if form.is_valid(): #もし、formの内容が正しい時は
            comment = form.save(commit=False) #formの内容はまだセーブしません!
            comment.post = article
            comment.author = request.user
            comment.save() #ユーザーを追加したのちにセーブ
    else:
        form = forms.CommentForm()

    print(article)
    return render(request, 'blog/article.html', {
        'article': article
        'form': form,
        'comments': comments
    }) #form と comment を追加

return renderの中身も、formcommentを追加しておきます。

urls.py

コメントは、article.html内に表記されるので、url自体は変わりません。
ここの変更はナシです。

article.html

記事の下のところにこのような記述を追加します。

article.html
    <div>
      <h3>コメント</h3>
      <form method="post" action="">
        {% csrf_token %}
        {{ form.as_p }}
        <input type="submit">
      </form>
      <hr>
      {% for comment in comments %}
        author: {{ comment.author }}<br>
        name: {{ comment.name }}<br>
        {{ comment.text }}<br>
        <hr>
      {% endfor %}
    </div>

入力フォームは<form method="POST" action=""></form>
で括ります。
POSTは情報を送る方なので、セキュリティのために(クロスサイトリクエストフォージェリ(CSRF) を防ぐために)
{% csrf_token %}
というものを入れます。
また、{{form}}だけでもよいのですが、各コンテンツを

タグで括る場合
{{form.as_p}}とします。pじゃなくても大丈夫です。

admin.py

最後にコメントのあれやこれやも管理ページから行えるようにするのであれば、

admin.py
from django.contrib import admin
from .models import Post, Comment #Comment追加

admin.site.register(Post)
admin.site.register(Comment) #この行追加

しておくと、localhost:8000/adminからCommentsが見られるようになります!

確認

スクリーンショット 2018-10-09 14.10.20.png loginuserは今は表示してありますが、本来ならば表示させるのはnameだけでよいでしょう。 しかし、loginuser(author)はあったほうがいいフォームのコンテンツです。 なぜなら、「書き込んだ人だけに削除権限を与える」ということをさせたいから! 次でやってみましょう。

参考情報

8
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?