Improving Number of Queries Generated by Django Comment's render_comment_list Template Tag

19 Sep · by Tim Kamanin · 2 min read

One of my Django apps uses Django Comments. To show a list of comments on a page I use this simple built-in template tag:

{% render_comment_list for object %}

All is fine, but I noticed that it loads user object per every comment line. So if you have 50 comments on a page you'll end up with 50 queries to get comment author object. Not a good thing but can be easily fixed. What we need here is to leverage Django ORM's prefetch_related() and load user object with a comment list on one go. (Of course you can go with select_related here, but I prefer prefetch_related here). Ok the fix is easy, we need to create our custom render_custom_comment_list template tag, that inherits almost everything from the default render_comment_list except one thing: a queryset. Here 's how I do it: 1) Create custom template_tag file and call it like '' or whatever. 2) And then write the following contents:

import django_comments
from django_comments.templatetags.comments import register, RenderCommentListNode

def render_custom_comment_list(parser, token):
This is our custom comment list template tag.
  return RenderCustomCommentListNode.handle_token(parser, token)

class RenderCustomCommentListNode(RenderCommentListNode):
We created our custom Render Comment List Node that extends default RenderCommentListNode.
def get_query_set(self, context):

  qs = super(RenderCustomCommentListNode, self).get_query_set(context)

  # The only additional thing we do here is we prefetch_related('user') to prefetch related user objects in one query.
  qs = qs.prefetch_related('user')

  return qs

As an outcome, instead of having 50+1 queries to get 50 comments out of the database, we got only 2: one to get comments out of db, another to get user objects. If you replace prefetch_related() with select_related() you will go down to only one query to load comments and user objects in one go. That simple!


Required for comment verification


it's not get_query_set at least it's not anymore, it's get_queryset()

changing that makes the whole snippet works

Reply · 1 year, 11 months ago