Creating Reddit Styled Comment System with Django

Published: 06/28/2019

Okay, so you are probably blogging in this platform and have used the comment system once in a while. Those who have will notice that the comment system is pretty much like reddit without the upvote and downvote feature. This is actually pretty simple to create and can be created using only one django template which calls itself recursively! Yes you heard that right, recursing on django templates. It might sound pretty fancy, but is basically a very simple idea.

So let's begin with the model. We create a simple django model with the following fields

  • user (a foreign key to user referring to the author of the comment)
  • article (a foreign key to article referring to the article on which the comment was made)
  • content (the content of the comment)
  • parent (a self-referential field referring to the parent comment, and is a root comment if there is no parent)
  • created_at (the time and date of comment creation)

Once the model is made, we can create the migrations and migrate the database using the commands `python makemigrations` and `python migrate`. Now that the model is created and the database is migrated, we need to create views for addition and deletion of comments. We can also create a view for editing comments but that is not what we will discuss in this article. So the add view should be a POST view which takes an `user_id`, `article_id`, `content` and `parent`. Once we validate these data, we can create a new `Comment` using

Comment.objects.create(user=User.objects.get(id=user_id), article=Article.objects.get(id=article_id), content=content, parent=parent)

Make sure that `parent` is `None` if there is no parent comment.

Okay we are almost done. We just need to work on the template now.

So we will render the template with the context variables `root_comments` which will have all the root comments of the article. Now we will create another template called `comments.html` which will be passed some variables called `comments`, `user`, etc from the driver template. It will look something like this

{% include "aldryn_newsblog/includes/comments.html" with comments=root_comments article=article user=user csrf_token=csrf_token only %}

This `comments.html` will run a for loop to display all the comments and with each iteration it will also call the same template recursively like this

{% include "aldryn_newsblog/includes/comments.html" with comments=comment.replies.all parent=comment article=article user=user csrf_token=csrf_token only %}

We need to use the keyword only so that only these variables are passed and not the parent template variables which will override the correct ones. So, we will also need to pass some variables like `user`, `crsf_token`, etc. Also, we need to create a form which will POST to the add comment view with every template to reply to the parent comment in that template.

We can also implement a bunch of other features like hiding the reply threads, adding recaptcha verification, etc. The code can be found on this repo. Feel free to use it or take help from the same.

That's it for today. Hope it helps.