Django: Link comments to objects for use with ORM QuerySet and filters

For a long time I've been meaning to find a more convenient way to filter comments. I really disliked the way we had to retrieve them through a tag, which either retrieved "all or nothing".

Sometimes it's necessary to retrieve comments from a subset of objects, such as comments for all blog posts "in category Cars".

To do this efficiently with minimal changes to the database, we'll need a proxy model. This proxy model has no table in the database but allows us to tweak the manager.

Firstly, define the proxy class and manager.

from django.conf import settings
from django.contrib.comments.managers import CommentManager
from django.contrib.comments.models import Comment

class CommentObjectManager(CommentManager):
def comments_for_objects(self, objects):
This is the magic query that links the `django_comments` table to the selected range of objects.
The reason why we have to do this is because the django_comments.object_pk field is stored as an string.
By casting it to an integer, we can then link it back to the original model without errors.
It's a bit hackish, but it's the cleanest way I found find to get it working.
# The usual filters for comments
qs = self.for_model(objects.model)
qs = qs.filter(site = settings.SITE_ID, is_public = True, is_removed = False)

# Link objects to the comments table
# This is for PostgreSQL. I'm sure there's a matching cast for MySQL and such.
extra_where = 'CAST(django_comments.object_pk AS int) IN (%s)' % ','.join([ '%s' % for obj in objects ])

return qs.extra(where = [extra_where]).order_by('-submit_date')

class CommentObject(Comment):
This dummy proxy class allows you to filter comments by certain objects.
class Meta:
proxy = True

objects = CommentObjectManager()

Now that the hard part is done, we just need a way to use it.

def for_posts_in_category(self, category, limit = 1500):
Example: Returns comments for the latest 1500 posts in the category given.
restriction = BlogPost.objects.all_in_category(category)[:limit]
return CommentObject.objects.comments_for_objects(restriction)

Ohhhhhhhh yeah~ time to celebrate!

Copyright © Twig's Tech Tips
Theme by BloggerThemes & TopWPThemes Sponsored by iBlogtoBlog