annotate gpp/forums/feeds.py @ 393:9af6bd45c1f8

Another try at #191 after getting some good advice in a django-users thread.
author Brian Neal <bgneal@gmail.com>
date Thu, 24 Mar 2011 00:15:34 +0000
parents 0398aae48807
children 63e4682d6482
rev   line source
bgneal@170 1 """This file contains the feed class for the forums application."""
bgneal@170 2
bgneal@176 3 from django.contrib.syndication.views import Feed
bgneal@170 4 from django.core.exceptions import ObjectDoesNotExist
bgneal@176 5 from django.shortcuts import get_object_or_404
bgneal@170 6
bgneal@393 7 from forums.models import Forum, Topic, Post
bgneal@176 8 from core.functions import copyright_str
bgneal@170 9
bgneal@170 10
bgneal@170 11 class ForumsFeed(Feed):
bgneal@176 12 """The Feed class for a specific forum"""
bgneal@170 13
bgneal@385 14 ttl = '60'
bgneal@176 15 author_name = 'Brian Neal'
bgneal@176 16 author_email = 'admin@surfguitar101.com'
bgneal@176 17
bgneal@176 18 def get_object(self, request, forum_slug):
bgneal@170 19 # only return public forums
bgneal@176 20 if forum_slug:
bgneal@176 21 forum = get_object_or_404(Forum, slug=forum_slug)
bgneal@387 22 if forum.id not in Forum.objects.public_forum_ids():
bgneal@170 23 raise ObjectDoesNotExist
bgneal@170 24 return forum
bgneal@170 25
bgneal@176 26 else:
bgneal@170 27 # return None to indicate we want a combined feed
bgneal@170 28 return None
bgneal@170 29
bgneal@170 30 def title(self, obj):
bgneal@170 31 if obj is None:
bgneal@170 32 forum_name = 'Combined'
bgneal@170 33 else:
bgneal@170 34 forum_name = obj.name
bgneal@170 35
bgneal@170 36 return 'SurfGuitar101.com %s Forum Feed' % forum_name
bgneal@170 37
bgneal@170 38 def link(self, obj):
bgneal@170 39 if obj is None:
bgneal@170 40 bits = ''
bgneal@170 41 else:
bgneal@170 42 bits = obj.slug + '/'
bgneal@170 43
bgneal@170 44 return '/feeds/forums/' + bits
bgneal@170 45
bgneal@170 46 def description(self, obj):
bgneal@170 47 if obj is None:
bgneal@170 48 return "User posts to SurfGuitar101.com forums."
bgneal@170 49 return obj.description
bgneal@170 50
bgneal@176 51 def feed_copyright(self):
bgneal@176 52 return copyright_str()
bgneal@170 53
bgneal@170 54 def items(self, obj):
bgneal@170 55 if obj is None:
bgneal@170 56 # return a combined feed of public forum threads
bgneal@387 57
bgneal@393 58 # This was tricky to do without suffering a large performance
bgneal@393 59 # impact. Because the number of forums is small, MySQL did not
bgneal@393 60 # try to use an index and ended up searching all the topics for
bgneal@393 61 # candidate posts. We work around this first getting a small list
bgneal@393 62 # of candidate topics, and then searching them. This is more
bgneal@393 63 # queries but a *lot* more time efficient.
bgneal@387 64
bgneal@393 65 forum_ids = Forum.objects.public_forum_ids()
bgneal@393 66 topic_ids = list(Topic.objects.filter(forum__in=forum_ids).order_by(
bgneal@393 67 '-update_date').values_list('id', flat=True)[:30])
bgneal@393 68 items = Post.objects.filter(topic__in=topic_ids)
bgneal@387 69
bgneal@170 70 else:
bgneal@393 71 items = Post.objects.filter(topic__forum=obj)
bgneal@393 72
bgneal@393 73 return items.order_by('-creation_date').select_related('topic', 'user',
bgneal@393 74 'topic__forum')[:30]
bgneal@170 75
bgneal@176 76 def item_title(self, item):
bgneal@176 77 return item.topic.name
bgneal@176 78
bgneal@176 79 def item_description(self, item):
bgneal@176 80 return item.html
bgneal@176 81
bgneal@176 82 def item_author_name(self, item):
bgneal@176 83 return item.user.username
bgneal@176 84
bgneal@170 85 def item_pubdate(self, item):
bgneal@170 86 return item.creation_date
bgneal@170 87
bgneal@170 88 def item_categories(self, item):
bgneal@170 89 return (item.topic.forum.name, )