0

Is it possible to get object with comments related to it? Right now django comment framework creates query for every object which has related comments and another queries for comments owners. Can I somehow avoid this? I use django 1.4 so prefetch_related is allowed.

szaman
  • 6,666
  • 13
  • 53
  • 81
  • The comments framework uses generic foreign keys to associate comments with objects. By definition, it requires multiple queries, because it has to lookup the `ContentType` and then use that to fetch the actual object. – Chris Pratt Mar 07 '12 at 15:14

1 Answers1

3

You could create a function that caches the count:

from django.contrib.contenttypes.models import ContentType
from django.contrib import comments

def get_comment_count_key(model):
    content_type = ContentType.objects.get_for_model(model)
    return 'comment_count_%s_%s' % (content_type.pk, model.pk)

def get_comment_count(model):
    key = get_comment_count_key(model)
    value = cache.get(key)
    if value is None:
        value = comments.get_model().objects.filter(
            content_type = ContentType.objects.get_for_model(model),
            object_pk = model.pk,
            site__pk = settings.SITE_ID
        ).count()
        cache.set(key, value)
    return value

You could extend the Comment model and add get_comment_count there. Or put get_comment_count as a template filter. It doesn't matter.

Of course, you would also need cache invalidation when a new comment is posted:

from django.db.models import signals
from django.contrib import comments

def refresh_comment_count(sender, instance, **kwargs):
    cache.delete(get_comment_count_key(instance.content_object))
    get_comment_count(instance.content_object)
post_save.connect(refresh_comment_count, sender=comments.get_model())
post_delete.connect(refresh_comment_count, sender=comments.get_model())

You could improve this last snippet, by using cache.incr() on comment_was_posted, and cache.decr() on post_delete but that's left as an exercise for you :)

jpic
  • 32,891
  • 5
  • 112
  • 113