comparison 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
comparison
equal deleted inserted replaced
392:79240675b903 393:9af6bd45c1f8
2 2
3 from django.contrib.syndication.views import Feed 3 from django.contrib.syndication.views import Feed
4 from django.core.exceptions import ObjectDoesNotExist 4 from django.core.exceptions import ObjectDoesNotExist
5 from django.shortcuts import get_object_or_404 5 from django.shortcuts import get_object_or_404
6 6
7 from forums.models import Forum 7 from forums.models import Forum, Topic, Post
8 from forums.models import Post
9 from core.functions import copyright_str 8 from core.functions import copyright_str
10 9
11 10
12 class ForumsFeed(Feed): 11 class ForumsFeed(Feed):
13 """The Feed class for a specific forum""" 12 """The Feed class for a specific forum"""
53 return copyright_str() 52 return copyright_str()
54 53
55 def items(self, obj): 54 def items(self, obj):
56 if obj is None: 55 if obj is None:
57 # return a combined feed of public forum threads 56 # return a combined feed of public forum threads
58 #
59 # This didn't work real well on InnoDb:
60 # items = Post.objects.filter(
61 # topic__forum__in=Forum.objects.public_forums())
62 #
63 # For some reason, MySQL wasn't using an index when "in" was used.
64 # So let's do this the hard way as a work-around:
65 57
66 public_forum_ids = Forum.objects.public_forum_ids() 58 # This was tricky to do without suffering a large performance
67 posts = [] 59 # impact. Because the number of forums is small, MySQL did not
68 for forum_id in public_forum_ids: 60 # try to use an index and ended up searching all the topics for
69 posts.extend(list(Post.objects.filter( 61 # candidate posts. We work around this first getting a small list
70 topic__forum=forum_id).order_by('-creation_date').select_related( 62 # of candidate topics, and then searching them. This is more
71 'topic', 'user', 'topic__forum')[:30])) 63 # queries but a *lot* more time efficient.
72 64
73 posts.sort(key=lambda x: x.creation_date, reverse=True) 65 forum_ids = Forum.objects.public_forum_ids()
74 return posts[:30] 66 topic_ids = list(Topic.objects.filter(forum__in=forum_ids).order_by(
67 '-update_date').values_list('id', flat=True)[:30])
68 items = Post.objects.filter(topic__in=topic_ids)
75 69
76 else: 70 else:
77 return Post.objects.filter(topic__forum__id=obj.id).order_by( 71 items = Post.objects.filter(topic__forum=obj)
78 '-creation_date').select_related('topic', 'user', 'topic__forum')[:30] 72
73 return items.order_by('-creation_date').select_related('topic', 'user',
74 'topic__forum')[:30]
79 75
80 def item_title(self, item): 76 def item_title(self, item):
81 return item.topic.name 77 return item.topic.name
82 78
83 def item_description(self, item): 79 def item_description(self, item):