Comments under Post

Question:

I created model Post and Comment, now I want to display comments from Post but I have a problem. In tutorial there is a line of code in html {% for comment in post.comments.all %} but isn’t working in my app. If I set {% for comment in comments %} it works but displays all comments from models (I want only comments from the post). How to fix that? Below I pasted my code.

models.py

from django.db import models


class Post(models.Model):
    title = models.CharField(max_length=64, blank=False, null=False)
    short_text = models.TextField(blank=False, null=False)
    text = models.TextField(blank=False, null=False)
    image = models.TextField(blank=False, null=False)
    date = models.DateTimeField(auto_now_add=True, blank=True)
    views = models.IntegerField(default=0)


class Comment(models.Model):
    post = models.ForeignKey('main.Post', on_delete=models.CASCADE)
    author = models.CharField(max_length=200)
    text = models.TextField()
    created_date = models.DateTimeField(auto_now_add=True, blank=True)
    approved_comment = models.BooleanField(default=False)

    def approve(self):
        self.approved_comment = True
        self.save()

    def __str__(self):
        return self.text

views.py

from django.shortcuts import get_object_or_404, render, redirect
from .models import Post, Comment


def index_pl(request):
    posts = Post.objects.all()
    return render(request, 'index_pl.html', {'posts': posts})


def single_article_pl(request, id):
    posts = get_object_or_404(Post, pk=id)
    posts.views = posts.views + 1
    posts.save()
    comments = Comment.objects.all()

    return render(request, 'single_article_pl.html', {'posts': posts, 'comments': comments})

html

{% for comment in post.comments.all %}
    <div class="comment">
        <div class="date">{{ comment.created_date }}</div>
        <strong>{{ comment.author }}</strong>
        <p>{{ comment.text|linebreaks }}</p>
    </div>
{% empty %}
    <p>No comments here yet :(</p>
{% endfor %}

admin.py

from django.contrib import admin
from .models import Post, Comment

admin.site.register(Post)
admin.site.register(Comment)
Asked By: pkucinski

||

Answers:

In tutorial there is a line of code in html {% for comment in post.comments.all %} but isn’t working in my app.

This is likely because they specified the related_name=… parameter [Django-doc] in the ForeignKey from Comment to Post, like:

# Option 1: set the related_name to 'comments'
class Comment(models.Model):
    post = models.ForeignKey(
        'main.Post',
        related_name='comments',
        on_delete=models.CASCADE
    )
    # …

The related_name=… specifies the name of the relation in reverse, so in this case accessing the Comments of a given Post object. By default this is model_name_set, so in this case comment_set.

You thus can either specify a related name; or you can acces the comment_set manager:

Option 2: use the default related_name
{% for comment in post.comment_set.all %}
    <div class="comment">
        <div class="date">{{ comment.created_date }}</div>
        <strong>{{ comment.author }}</strong>
        <p>{{ comment.text|linebreaks }}</p>
    </div>
{% empty %}
    <p>No comments here yet :(</p>
{% endfor %}
Answered By: Willem Van Onsem
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.