annotate gpp/forums/feeds.py @ 388:c3231af55778

For #191; r410 is wrong: it is returning the wrong posts. Rework. MySQL is not using an index on our query, and it is taking 10+ seconds. Replace this slow query with a loop that loops over the public forums, then sorts and returns the posts.
author Brian Neal <bgneal@gmail.com>
date Sat, 19 Mar 2011 05:03:51 +0000
parents b15726767ab8
children 0398aae48807
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@170 7 from forums.models import Forum
bgneal@170 8 from forums.models import Post
bgneal@176 9 from core.functions import copyright_str
bgneal@170 10
bgneal@170 11
bgneal@170 12 class ForumsFeed(Feed):
bgneal@176 13 """The Feed class for a specific forum"""
bgneal@170 14
bgneal@385 15 ttl = '60'
bgneal@176 16 author_name = 'Brian Neal'
bgneal@176 17 author_email = 'admin@surfguitar101.com'
bgneal@176 18
bgneal@176 19 def get_object(self, request, forum_slug):
bgneal@170 20 # only return public forums
bgneal@176 21 if forum_slug:
bgneal@176 22 forum = get_object_or_404(Forum, slug=forum_slug)
bgneal@387 23 if forum.id not in Forum.objects.public_forum_ids():
bgneal@170 24 raise ObjectDoesNotExist
bgneal@170 25 return forum
bgneal@170 26
bgneal@176 27 else:
bgneal@170 28 # return None to indicate we want a combined feed
bgneal@170 29 return None
bgneal@170 30
bgneal@170 31 def title(self, obj):
bgneal@170 32 if obj is None:
bgneal@170 33 forum_name = 'Combined'
bgneal@170 34 else:
bgneal@170 35 forum_name = obj.name
bgneal@170 36
bgneal@170 37 return 'SurfGuitar101.com %s Forum Feed' % forum_name
bgneal@170 38
bgneal@170 39 def link(self, obj):
bgneal@170 40 if obj is None:
bgneal@170 41 bits = ''
bgneal@170 42 else:
bgneal@170 43 bits = obj.slug + '/'
bgneal@170 44
bgneal@170 45 return '/feeds/forums/' + bits
bgneal@170 46
bgneal@170 47 def description(self, obj):
bgneal@170 48 if obj is None:
bgneal@170 49 return "User posts to SurfGuitar101.com forums."
bgneal@170 50 return obj.description
bgneal@170 51
bgneal@176 52 def feed_copyright(self):
bgneal@176 53 return copyright_str()
bgneal@170 54
bgneal@170 55 def items(self, obj):
bgneal@170 56 if obj is None:
bgneal@170 57 # return a combined feed of public forum threads
bgneal@387 58 #
bgneal@387 59 # This didn't work real well on InnoDb:
bgneal@387 60 # items = Post.objects.filter(
bgneal@387 61 # topic__forum__in=Forum.objects.public_forums())
bgneal@387 62 #
bgneal@388 63 # For some reason, MySQL wasn't using an index when "in" was used.
bgneal@388 64 # So let's do this the hard way as a work-around:
bgneal@387 65
bgneal@387 66 public_forum_ids = Forum.objects.public_forum_ids()
bgneal@388 67 posts = []
bgneal@388 68 for forum_id in public_forum_ids:
bgneal@388 69 posts.extend(list(Post.objects.filter(
bgneal@388 70 topic__forum__id=forum_id).order_by('-creation_date').select_related(depth=2)[:30]))
bgneal@387 71
bgneal@388 72 posts.sort(key=lambda x: x.creation_date, reverse=True)
bgneal@388 73 return posts[:30]
bgneal@387 74
bgneal@170 75 else:
bgneal@388 76 return Post.objects.filter(topic__forum__id=obj.id).order_by(
bgneal@388 77 '-creation_date').select_related(depth=2)[:30]
bgneal@170 78
bgneal@176 79 def item_title(self, item):
bgneal@176 80 return item.topic.name
bgneal@176 81
bgneal@176 82 def item_description(self, item):
bgneal@176 83 return item.html
bgneal@176 84
bgneal@176 85 def item_author_name(self, item):
bgneal@176 86 return item.user.username
bgneal@176 87
bgneal@170 88 def item_pubdate(self, item):
bgneal@170 89 return item.creation_date
bgneal@170 90
bgneal@170 91 def item_categories(self, item):
bgneal@170 92 return (item.topic.forum.name, )