bgneal@170: """This file contains the feed class for the forums application.""" bgneal@170: bgneal@176: from django.contrib.syndication.views import Feed bgneal@170: from django.core.exceptions import ObjectDoesNotExist bgneal@176: from django.shortcuts import get_object_or_404 bgneal@170: bgneal@393: from forums.models import Forum, Topic, Post bgneal@176: from core.functions import copyright_str bgneal@170: bgneal@170: bgneal@170: class ForumsFeed(Feed): bgneal@176: """The Feed class for a specific forum""" bgneal@170: bgneal@385: ttl = '60' bgneal@176: author_name = 'Brian Neal' bgneal@176: author_email = 'admin@surfguitar101.com' bgneal@176: bgneal@176: def get_object(self, request, forum_slug): bgneal@170: # only return public forums bgneal@176: if forum_slug: bgneal@176: forum = get_object_or_404(Forum, slug=forum_slug) bgneal@387: if forum.id not in Forum.objects.public_forum_ids(): bgneal@170: raise ObjectDoesNotExist bgneal@170: return forum bgneal@170: bgneal@176: else: bgneal@170: # return None to indicate we want a combined feed bgneal@170: return None bgneal@170: bgneal@170: def title(self, obj): bgneal@170: if obj is None: bgneal@170: forum_name = 'Combined' bgneal@170: else: bgneal@170: forum_name = obj.name bgneal@170: bgneal@170: return 'SurfGuitar101.com %s Forum Feed' % forum_name bgneal@170: bgneal@170: def link(self, obj): bgneal@170: if obj is None: bgneal@170: bits = '' bgneal@170: else: bgneal@170: bits = obj.slug + '/' bgneal@170: bgneal@170: return '/feeds/forums/' + bits bgneal@170: bgneal@170: def description(self, obj): bgneal@170: if obj is None: bgneal@170: return "User posts to SurfGuitar101.com forums." bgneal@170: return obj.description bgneal@170: bgneal@176: def feed_copyright(self): bgneal@176: return copyright_str() bgneal@170: bgneal@170: def items(self, obj): bgneal@170: if obj is None: bgneal@170: # return a combined feed of public forum threads bgneal@387: bgneal@393: # This was tricky to do without suffering a large performance bgneal@393: # impact. Because the number of forums is small, MySQL did not bgneal@393: # try to use an index and ended up searching all the topics for bgneal@396: # candidate posts. We work around this by first getting a small list bgneal@393: # of candidate topics, and then searching them. This is more bgneal@393: # queries but a *lot* more time efficient. bgneal@387: bgneal@393: forum_ids = Forum.objects.public_forum_ids() bgneal@393: topic_ids = list(Topic.objects.filter(forum__in=forum_ids).order_by( bgneal@393: '-update_date').values_list('id', flat=True)[:30]) bgneal@393: items = Post.objects.filter(topic__in=topic_ids) bgneal@387: bgneal@170: else: bgneal@393: items = Post.objects.filter(topic__forum=obj) bgneal@393: bgneal@393: return items.order_by('-creation_date').select_related('topic', 'user', bgneal@393: 'topic__forum')[:30] bgneal@170: bgneal@176: def item_title(self, item): bgneal@176: return item.topic.name bgneal@176: bgneal@176: def item_description(self, item): bgneal@176: return item.html bgneal@176: bgneal@176: def item_author_name(self, item): bgneal@176: return item.user.username bgneal@176: bgneal@170: def item_pubdate(self, item): bgneal@170: return item.creation_date bgneal@170: bgneal@170: def item_categories(self, item): bgneal@170: return (item.topic.forum.name, )