tsmith41094
tsmith41094

Reputation: 89

How to retrieve all the comments for a post using related names?

I am trying to create a comment page for a blog-style site that will list all of the previous comments for a single related post.

I am having trouble figuring out how to structure the view to get what I'm looking for. I have been trying to use related names to get the data but am not sure if that is the right method.

Here are my models:

class Post(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE, null=True)
    title = models.CharField(max_length=128)
    content = models.TextField()
    image = models.ImageField(upload_to='post_pics', blank=True)
    date_posted = models.DateTimeField(default=timezone.now)

    def get_absolute_url(self):
        return reverse('home')

class Comment(models.Model):
    post = models.ForeignKey(Post, on_delete=models.CASCADE, related_name='comments')
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    comment = models.TextField()
    date_created = models.DateTimeField(default=timezone.now)

    def get_absolute_url(self):
        return reverse('home')

And here is my view:

class CommentCreateView(LoginRequiredMixin, CreateView):
    model = Comment
    template_name = 'home/comment-form.html'
    fields = ['comment',]

    def get_context_data(self, **kwargs):
        context = super(CommentCreateView, self).get_context_data(**kwargs)
        context['post'] = Post.objects.get(pk=self.kwargs['pk'])
        comments = Post.comments.all()
        context['comments'] = comments
        return context

    def form_valid(self, form):
        form.instance.user = self.request.user
        form.instance.post = Post.objects.get(pk=self.kwargs['pk'])
        return super().form_valid(form)

I have been trying a bunch of different things. The above is just my latest attempt. When I try to run this one I get a 'ReverseManyToOneDescriptor' object has no attribute 'all' error.

I don't know if I need to run a get_queryset() function or maybe call a queryset at the beginning of the view?

Know this is probably a very basic issue but I appreciate the help!

Upvotes: 1

Views: 977

Answers (2)

Aurélien
Aurélien

Reputation: 1655

To get the comments, you can use a filter()

Class CommentCreateView(LoginRequiredMixin, CreateView):
    model = Comment
    template_name = 'home/comment-form.html'
    fields = ['comment',]

    def get_context_data(self, **kwargs):
        context = super(CommentCreateView, self).get_context_data(**kwargs)
        post = Post.objects.get(pk=self.kwargs['pk'])
        context['post'] = post
        comments = Comment.objects.filter(post=post)
        context['comments'] = comments
        return context

Upvotes: 1

ruddra
ruddra

Reputation: 51978

You do not need to pass comments to template, you can simply use:

{% for comment in post.comments.all %}
    {{ comment.comment }}
{% endfor %}

It is possible because you already defined related_name='comments' in Comment model.

Upvotes: 1

Related Questions