django displaying posts and comments

Question:

this is models.py

class Post(models.Model):
    author = models.ForeignKey('auth.User', on_delete=models.CASCADE)
    title = models.CharField(max_length=100)
    content = models.TextField()
    date = models.DateTimeField(default=timezone.now)

    def write(self):
        self.date = timezone.now()
        self.save()

    def __str__(self):
        return self.title

class Comment(models.Model):
    post = models.ForeignKey('humorge.post', on_delete=models.CASCADE, related_name='comments')
    author = models.CharField(max_length=100)
    content = models.TextField()
    date = models.DateTimeField(default=timezone.now)

    def add_coment(self):
        self.date = timezone.now()
        self.save()

    def __str__(self):
        return self.content

and this is views.py

def mainpage(request):
    return render(request, 'index.html')

def post(request):
    datas = Post.objects.order_by('-date')
    comments = Comment.objects.all()
    return render(request, 'post.html', {'datas': datas, 'comments': comments})

and this is template

{% extends 'layout.html' %}

{% block main %}
<div class="container">
  {% for data in datas %}
    <div class="row">
      <div class="col s12 m7">
        <div class="card">
          <div class="card-image">
            <img src="#">
            <span class="card-title">{{ data.title }}</span>
          </div>
          <div class="card-content">
            <p>{{ data.content }}</p>
          </div>
          <div class="card-action">
            <p>{{ data.date }}</p>
          </div>
          <div class="card-action">
            {% for comment in comments %}
              {% if comment.post == data.title %}
                {{ comment.date }}<br>
                <strong>{{ comment.author }}</strong>
                <p>{{ comment.content }}</p>
              {% endif %}
            {% empty %}
              <p>There is no comments</p>
            {% endfor %}
          </div>
        </div>
      </div>
    </div>
  {% empty %}
    <p>there is no posts</p>
  {% endfor %}
</div>
{% endblock %}

I want to display posts and comments

when I try to have two posts and each post has one comments

it shows like each posts has two comments

so I added {% if comment.post == data.title %} in the template

but it shows nothing

I tried to find answers on google, youtube, some tutorial page….

but what I found was just how to add comments on posts..

or displaying post and comment but actually one post one comment

Asked By: MINSIK

||

Answers:

You don’t need to query list of comments in you views, you need just posts:

def post(request):
    datas = Post.objects.order_by('-date')
    return render(request, 'post.html', {'datas': datas})

And in template you can then do something like this:

{% block main %}
<div class="container">
  {% for data in datas %}
    ...
      <div class="card-action">
        {% for comment in data.comments.all %}  // Gives list of all comments for the current post ie. data
            {{ comment.date }}<br>
            <strong>{{ comment.author }}</strong>
            <p>{{ comment.content }}</p>
        {% empty %}
          <p>There is no comments</p>
        {% endfor %}
      </div>
      {% empty %}
      <p>there is no posts</p>
    {% endfor %}
  </div>
  ...
{% endblock %}

Btw the thing that’s wrong with the if condition in your template is that you are doing {% if comment.post == data.title %} but commpent.post is an object of model Post and post.title is string, so they are never equal. What you need to do is {% if comment.post == data %} or {% if comment.post.title == data.title %}

Answered By: Vaibhav Vishal

In your post view, instead of:

comment = Comment.objects.all()

which will fetch all the comments irrespective of the post it belongs to,

do this:

comment = datas.comments.all()

where the ‘comments’ is the related_name declared in the post field of the Comment model.

Answered By: onyenzedon
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.