DEV Community

Cover image for How to create a Comment Section for your Django Blog!

How to create a Comment Section for your Django Blog!

Radu-Alexandru B on September 28, 2020

Hi! This mini-tutorial will focus on creating a Comment Section for adding (without update/delete) comments to each blog post. We will implement t...
Collapse
 
madeleineatkins profile image
Madeleine Atkins

Thanks for sharing this wonderful post. Homepage

Collapse
 
radualexandrub profile image
Radu-Alexandru B

Glad that I helped you!

Welcome de DEV Community, have a wonderful week!

Collapse
 
raybesiga profile image
Ray Besiga

Hi @Radu,

Great article but I just want to point out a few issues. The first is in your BlogPostDetailView

    def get_context_data(self, **kwargs):
        data = super().get_context_data(**kwargs)

        comments_connected = BlogComment.objects.filter(
            blogpost_connected=self.get_object()).order_by('-date_posted')
Enter fullscreen mode Exit fullscreen mode

This is bound to throw a Type Error. In this case, it will be an object not callable error.

The other issue I see arising is with the post:

 def post(self, request, *args, **kwargs):
        new_comment = BlogComment(content=request.POST.get('content'),
                                  author=self.request.user,
                                  blogpost_connected=self.get_object())
Enter fullscreen mode Exit fullscreen mode

The blogpost_connected should be an instance of the BlogPost and not the BlogComment. I hope this is helpful. Best regards.

Collapse
 
ninanolets profile image
Nina Noleto

Hey, thanks for this mini tutorial! I appreciate that it's detailed but simple. Made an account here just to say thanks, it kinda saved me today :)

Collapse
 
radualexandrub profile image
Radu-Alexandru B

Thank you!

I like to break the whole code into smaller steps, without puzzling the viewer with extra complexity or missing code parts. However, it's hard to find the extra time to write those kinds of posts, but appreciations like these motivate me.

Welcome to DEV Community!

Collapse
 
ianrmaher profile image
IanRMaher

Thanks for sharing this post with us I was searching for these tip from many days then my best friend suggests me your post now she need help regarding dissertation proofreading services and I want to help her. So if anyone knows about this please let me know.

Collapse
 
leandropaolo1 profile image
leandropaolo1

great tutorial, awesome code. Thanks man, you made my day. I also made an account today just to leave you a message. PS it never happens

Collapse
 
jiraiyasennin profile image
Dostow**->

What if i don't need the user to be logged in? I'm working in a comment system for my personal site without a registration system :-)
Thanks.

Collapse
 
radualexandrub profile image
Radu-Alexandru B

Hmm... I didn't think about this option. But the process should be even simpler than the instructions I've written here.

Firstly, in our models.py we don't need an author based on User anymore, we will just use TextField():

# models.py
from django.db import models
from django.utils import timezone

class BlogComment(models.Model):
    blogpost_connected = models.ForeignKey(
        BlogPost, related_name='comments', on_delete=models.CASCADE)
    author = TextField()
    content = TextField()
    date_posted = models.DateTimeField(default=timezone.now)

    def __str__(self):
        return self.blogpost_connected.title[:40]
Enter fullscreen mode Exit fullscreen mode

[Optional] We can still return the number of comments if we want in our main BlogPost class model in models.py:

# models.py
class BlogPost(models.Model):
    title = models.CharField(max_length=100)
    ...

    @property
    def number_of_comments(self):
        return BlogComment.objects.filter(blogpost_connected=self).count()
Enter fullscreen mode Exit fullscreen mode

Make the changes to our database:

# CLI/Terminal
>> cd C:\Projects\...\YourDjangoAppMainFolder
>> python manage.py makemigrations
>> python manage.py migrate
Enter fullscreen mode Exit fullscreen mode

Create the same forms.py with an author:

# forms.py
from django import forms
from .models import BlogComment

class NewCommentForm(forms.ModelForm):
    class Meta:
        model = BlogComment
        fields = ['author', 'content']
Enter fullscreen mode Exit fullscreen mode

And now in views.py we don't need to check if self.request.user.is_authenticated anymore, we will just send the form as context to our HTML-based blogpost_detail.html.

# views.py
from .models import BlogPost, BlogComment
from .forms import NewCommentForm

class BlogPostDetailView(DetailView):
    model = BlogPost
    # template_name = MainApp/BlogPost_detail.html
    # context_object_name = 'object'

    def get_context_data(self, **kwargs):
        data = super().get_context_data(**kwargs)

        comments_connected = BlogComment.objects.filter(
            blogpost_connected=self.get_object()).order_by('date_posted')
        data['comments'] = comments_connected
        data['comment_form'] = NewCommentForm( )

        return data

    def post(self, request, *args, **kwargs):
        new_comment = BlogComment(content=request.POST.get('content'),
                                  author=request.POST.get('author'),
                                  blogpost_connected=self.get_object())
        new_comment.save()
        return self.get(self, request, *args, **kwargs)
Enter fullscreen mode Exit fullscreen mode

And finally in our blogpost_detail.html we'll show directly the forms without checking if user.is_authenticated.

<!-- COMMENTS  -->
<h2>Leave your comment!</h2>
<div id="comments_section">

  <form method="POST">
    {% csrf_token %}
    <div class="form-group">
      {{ comment_form }}
      <button class="btn btn-info" type="submit">Add comment <i class="fas fa-comments"></i></button>
    </div>
  </form>

  {% if comments %}
  <strong class="text-secondary">{{ object.number_of_comments }} Comment{{ object.number_of_comments|pluralize }}</strong>
  <hr>
  <ul>
    {% for comment in comments %}
    <li>           
     <div>
        <span>
          <strong class="text-info">{{ comment.author }} </strong>
          <small class="text-muted">{{ comment.date_posted }}</small>
        </span>
        <p>
          {{ comment.content|safe }}
        </p>
      </div>
    </li>
    {% endfor %}
  </ul>
  {% else %}
    <strong class="text-secondary">No comments yet...</strong>
  {% endif %}

</div>
Enter fullscreen mode Exit fullscreen mode

Hope all of these will work. Good Luck!

Collapse
 
tejkrishna profile image
tejkrishna • Edited

Thanks for publishing Python information. This is very understanding and useful to me

Collapse
 
jiraiyasennin profile image
Dostow**->

Amazing!! Thank you a lot!! It's more or less how i thought it should be, now i can continue with the project :-D

Collapse
 
simfpayn profile image
simfpayn

Students should check for certain terms while examining the best cv writing service london as some essay reviews regularly utilize keywords such as me and I, signaling that they are aiming to generate credibility and obtain confidence. Because they want to be honest, genuine customers or users prefer nouns.

Collapse
 
salim1421 profile image
salim1421

Thanks Man

Collapse
 
trodojastine profile image
Jastine Trodo
Collapse
 
imbiru143 profile image
Birendra Bohara

what should i do if i have to use same comment model in different place

Collapse
 
marobo profile image
Onorio de Jesus Afonso

test