Adding comments to the post detail template
We have created the functionality to manage comments for a post. Now, we will need to adapt our post/detail.html template to do the following things:
- Display the total number of comments for the post
- Display the list of comments
- Display a form for users to add a new comment
First, we will add the total comments. Open the post/detail.html template and append the following code to the content block:
{% with comments.count as total_comments %}
<h2>
{{ total_comments }} comment{{ total_comments|pluralize }}
</h2>
{% endwith %}
We are using the Django ORM in the template, executing the QuerySet comments.count(). Note that Django template language doesn't use parentheses for calling methods. The {% with %} tag allows us to assign a value to a new variable that will be available to be used until the {% endwith %} tag.
The {% with %} template tag is useful to avoid hitting the database or accessing expensive methods multiple times.
We use the pluralize template filter to display a plural suffix for the word comment, depending on the total_comments value. Template filters take the value of the variable they are applied to as their input and return a computed value. We will discuss template filters in Chapter 3, Extending Your Blog Application.
The pluralize template filter returns a string with the letter "s" if the value is different from 1. The preceding text will be rendered as 0 comments, 1 comment, or N comments. Django includes plenty of template tags and filters that help you display information in the way you want.
Now, let's include the list of comments. Append the following lines to the post/detail.html template below the preceding code:
{% for comment in comments %}
<p class="comment">
<p class="info">
Comment {{ forloop.counter }} by {{ comment.name }}
{{ comment.created }}
</p>
{{ comment.body|linebreaks }}
</p>
{% empty %}
<p>There are no comments yet.</p>
{% endfor %}
We use the {% for %} template tag to loop through comments. We display a default message if the comments list is empty, informing our users that there are no comments on this post yet. We enumerate comments with the {{ forloop.counter }} variable, which contains the loop counter in each iteration. Then, we display the name of the user who posted the comment, the date, and the body of the comment.
Finally, you need to render the form or display a successful message instead when it is successfully submitted. Add the following lines just below the preceding code:
{% if new_comment %}
<h2>Your comment has been added.</h2>
{% else %}
<h2>Add a new comment</h2>
<form action="." method="post">
{{ comment_form.as_p }}
{% csrf_token %}
<p><input type="submit" value="Add comment"></p>
</form>
{% endif %}
The code is pretty straightforward: if the new_comment object exists, we display a success message because the comment was successfully created. Otherwise, we render the form with a paragraph <p> element for each field and include the CSRF token required for POST requests. Open http://127.0.0.1:8000/blog/ in your browser and click on a post title to take a look at its detail page. You will see something like the following screenshot:
Add a couple of comments using the form. They should appear under your post in chronological order, as follows:
Open http://127.0.0.1:8000/admin/blog/comment/ in your browser. You will see the admin page with the list of comments you created. Click on one of them to edit it, uncheck the Active checkbox, and click on the Save button. You will be redirected to the list of comments again, and the Active column will display an inactive icon for the comment. It should look like the first comment in the following screenshot:
If you return to the post detail view, you will note that the deleted comment is not displayed any more; neither is it being counted for the total number of comments. Thanks to the active field, you can deactivate inappropriate comments and avoid showing them in your posts.