changeset 469:3b30286adba5

Smarter search index updating for forums. This work is for #227.
author Brian Neal <bgneal@gmail.com>
date Wed, 17 Aug 2011 01:02:08 +0000
parents ad4b63fbc584
children d9b6c4ec1977
files gpp/bio/search_indexes.py gpp/custom_search.py gpp/custom_search/__init__.py gpp/custom_search/forms.py gpp/custom_search/indexes.py gpp/downloads/search_indexes.py gpp/forums/forms.py gpp/forums/search_indexes.py gpp/forums/signals.py gpp/forums/views/main.py gpp/news/search_indexes.py gpp/podcast/search_indexes.py gpp/urls.py gpp/weblinks/search_indexes.py gpp/ygroup/search_indexes.py
diffstat 14 files changed, 152 insertions(+), 71 deletions(-) [+]
line wrap: on
line diff
--- a/gpp/bio/search_indexes.py	Sun Aug 07 03:38:42 2011 +0000
+++ b/gpp/bio/search_indexes.py	Wed Aug 17 01:02:08 2011 +0000
@@ -1,7 +1,7 @@
 """Haystack search index for the bio application."""
 from haystack.indexes import *
 from haystack import site
-from custom_search import CondQueuedSearchIndex
+from custom_search.indexes import CondQueuedSearchIndex
 
 from bio.models import UserProfile
 
--- a/gpp/custom_search.py	Sun Aug 07 03:38:42 2011 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,62 +0,0 @@
-"""
-This module contains custom code to tailor the Haystack search application to
-our needs.
-
-"""
-import urllib
-
-from django import forms
-from haystack.forms import ModelSearchForm
-from queued_search.indexes import QueuedSearchIndex
-
-
-MODEL_CHOICES = (
-    ('forums.topic', 'Forum Topics'),
-    ('forums.post', 'Forum Posts'),
-    ('news.story', 'News Stories'),
-    ('bio.userprofile', 'User Profiles'),
-    ('weblinks.link', 'Links'),
-    ('downloads.download', 'Downloads'),
-    ('podcast.item', 'Podcasts'),
-    ('ygroup.post', 'Yahoo Group Archives'),
-)
-
-
-class CustomModelSearchForm(ModelSearchForm):
-    """
-    This customized ModelSearchForm allows us to explictly label and order
-    the model choices.
-
-    """
-    q = forms.CharField(required=False, label='',
-            widget=forms.TextInput(attrs={'class': 'text', 'size': 48}))
-
-    def __init__(self, *args, **kwargs):
-        super(CustomModelSearchForm, self).__init__(*args, **kwargs)
-        self.fields['models'] = forms.MultipleChoiceField(choices=MODEL_CHOICES,
-                label='', widget=forms.CheckboxSelectMultiple)
-
-
-class CondQueuedSearchIndex(QueuedSearchIndex):
-    """
-    This customized version of QueuedSearchIndex conditionally enqueues items
-    to be indexed by calling the can_index() method.
-
-    """
-    def can_index(self, instance):
-        """
-        The default is to index all instances. Override this method to
-        customize the behavior. This will be called on all update operations.
-
-        """
-        return True
-
-    def enqueue(self, action, instance):
-        """
-        This method enqueues the instance only if the can_index() method
-        returns True.
-
-        """
-        if (action == 'update' and self.can_index(instance) or
-                action == 'delete'):
-            super(CondQueuedSearchIndex, self).enqueue(action, instance)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gpp/custom_search/forms.py	Wed Aug 17 01:02:08 2011 +0000
@@ -0,0 +1,34 @@
+"""
+This module contains custom forms to tailor the Haystack search application to
+our needs.
+
+"""
+from django import forms
+from haystack.forms import ModelSearchForm
+
+
+MODEL_CHOICES = (
+    ('forums.topic', 'Forum Topics'),
+    ('forums.post', 'Forum Posts'),
+    ('news.story', 'News Stories'),
+    ('bio.userprofile', 'User Profiles'),
+    ('weblinks.link', 'Links'),
+    ('downloads.download', 'Downloads'),
+    ('podcast.item', 'Podcasts'),
+    ('ygroup.post', 'Yahoo Group Archives'),
+)
+
+
+class CustomModelSearchForm(ModelSearchForm):
+    """
+    This customized ModelSearchForm allows us to explictly label and order
+    the model choices.
+
+    """
+    q = forms.CharField(required=False, label='',
+            widget=forms.TextInput(attrs={'class': 'text', 'size': 48}))
+
+    def __init__(self, *args, **kwargs):
+        super(CustomModelSearchForm, self).__init__(*args, **kwargs)
+        self.fields['models'] = forms.MultipleChoiceField(choices=MODEL_CHOICES,
+                label='', widget=forms.CheckboxSelectMultiple)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gpp/custom_search/indexes.py	Wed Aug 17 01:02:08 2011 +0000
@@ -0,0 +1,31 @@
+"""
+This module contains custom search indexes to tailor the Haystack search
+application to our needs.
+
+"""
+from queued_search.indexes import QueuedSearchIndex
+
+
+class CondQueuedSearchIndex(QueuedSearchIndex):
+    """
+    This customized version of QueuedSearchIndex conditionally enqueues items
+    to be indexed by calling the can_index() method.
+
+    """
+    def can_index(self, instance):
+        """
+        The default is to index all instances. Override this method to
+        customize the behavior. This will be called on all update operations.
+
+        """
+        return True
+
+    def enqueue(self, action, instance):
+        """
+        This method enqueues the instance only if the can_index() method
+        returns True.
+
+        """
+        if (action == 'update' and self.can_index(instance) or
+                action == 'delete'):
+            super(CondQueuedSearchIndex, self).enqueue(action, instance)
--- a/gpp/downloads/search_indexes.py	Sun Aug 07 03:38:42 2011 +0000
+++ b/gpp/downloads/search_indexes.py	Wed Aug 17 01:02:08 2011 +0000
@@ -1,7 +1,7 @@
 """Haystack search index for the downloads application."""
 from haystack.indexes import *
 from haystack import site
-from custom_search import CondQueuedSearchIndex
+from custom_search.indexes import CondQueuedSearchIndex
 
 from downloads.models import Download
 
--- a/gpp/forums/forms.py	Sun Aug 07 03:38:42 2011 +0000
+++ b/gpp/forums/forms.py	Wed Aug 17 01:02:08 2011 +0000
@@ -1,5 +1,6 @@
 """
 Forms for the forums application.
+
 """
 from django import forms
 from django.conf import settings
@@ -9,6 +10,7 @@
 from forums.models import Post
 from forums.attachments import AttachmentProcessor
 import forums.permissions as perms
+from forums.signals import notify_new_topic, notify_new_post
 
 
 class NewPostForm(forms.Form):
@@ -55,6 +57,7 @@
                 user_ip=ip)
         post.save()
         self.attach_proc.save_attachments(post)
+        notify_new_post(post)
         return post
 
 
@@ -131,6 +134,9 @@
 
         self.attach_proc.save_attachments(post)
 
+        notify_new_topic(topic)
+        notify_new_post(post)
+
         return topic
 
 
--- a/gpp/forums/search_indexes.py	Sun Aug 07 03:38:42 2011 +0000
+++ b/gpp/forums/search_indexes.py	Wed Aug 17 01:02:08 2011 +0000
@@ -1,9 +1,10 @@
 """Haystack search index for the weblinks application."""
 from haystack.indexes import *
 from haystack import site
-from custom_search import CondQueuedSearchIndex
+from custom_search.indexes import CondQueuedSearchIndex
 
 from forums.models import Forum, Topic, Post
+from forums.signals import topic_content_update, post_content_update
 
 
 class TopicIndex(CondQueuedSearchIndex):
@@ -17,6 +18,12 @@
     def get_updated_field(self):
         return 'update_date'
 
+    def _setup_save(self, model):
+        topic_content_update.connect(self.enqueue_save)
+
+    def _teardown_save(self, model):
+        topic_content_update.disconnect(self.enqueue_save)
+
     def can_index(self, instance):
         return instance.forum.id in Forum.objects.public_forum_ids()
 
@@ -33,6 +40,12 @@
     def get_updated_field(self):
         return 'update_date'
 
+    def _setup_save(self, model):
+        post_content_update.connect(self.enqueue_save)
+
+    def _teardown_save(self, model):
+        post_content_update.disconnect(self.enqueue_save)
+
     def can_index(self, instance):
         return instance.topic.forum.id in Forum.objects.public_forum_ids()
 
--- a/gpp/forums/signals.py	Sun Aug 07 03:38:42 2011 +0000
+++ b/gpp/forums/signals.py	Wed Aug 17 01:02:08 2011 +0000
@@ -1,8 +1,10 @@
 """
-Signal handlers for the forums application.
+Signal handlers & signals for the forums application.
+
 """
 from django.db.models.signals import post_save
 from django.db.models.signals import post_delete
+import django.dispatch
 
 from forums.models import Forum, Topic, Post
 from forums.views.subscriptions import notify_topic_subscribers
@@ -65,3 +67,54 @@
 
 post_save.connect(on_post_save, sender=Post, dispatch_uid='forums.signals')
 post_delete.connect(on_post_delete, sender=Post, dispatch_uid='forums.signals')
+
+
+# Signals for the forums application.
+#
+# This signal is sent when a topic has had its textual content (title) changed.
+# The provided arguments are: 
+#   sender - the topic model instance 
+#   instance - the topic model instance
+#   created - True if the topic is new, False if updated
+
+topic_content_update = django.dispatch.Signal(providing_args=['action'])
+
+# This signal is sent when a post has had its textual content (body) changed.
+# The provided arguments are: 
+#   sender - the post model instance 
+#   instance - the topic model instance
+#   created - True if the post is new, False if updated
+
+post_content_update = django.dispatch.Signal(providing_args=['action'])
+
+
+def notify_new_topic(topic):
+    """
+    Sends the topic_content_update signal for a new topic instance.
+
+    """
+    topic_content_update.send_robust(topic, instance=topic, created=True)
+
+
+def notify_updated_topic(topic):
+    """
+    Sends the topic_content_update signal for an updated topic instance.
+
+    """
+    topic_content_update.send_robust(topic, instance=topic, created=False)
+
+
+def notify_new_post(post):
+    """
+    Sends the post_content_update signal for a new post instance.
+
+    """
+    post_content_update.send_robust(post, instance=post, created=True)
+
+
+def notify_updated_post(post):
+    """
+    Sends the post_content_update signal for an updated post instance.
+
+    """
+    post_content_update.send_robust(post, instance=post, created=False)
--- a/gpp/forums/views/main.py	Sun Aug 07 03:38:42 2011 +0000
+++ b/gpp/forums/views/main.py	Wed Aug 17 01:02:08 2011 +0000
@@ -36,6 +36,8 @@
 
 from forums.attachments import AttachmentProcessor
 import forums.permissions as perms
+from forums.signals import (notify_new_topic, notify_updated_topic,
+        notify_new_post, notify_updated_post)
 
 #######################################################################
 
@@ -440,10 +442,12 @@
             post = form.save(commit=False)
             post.touch()
             post.save()
+            notify_updated_post(post)
 
             # if we are editing a first post, save the parent topic as well
             if topic_name:
                 post.topic.save()
+                notify_updated_topic(post.topic)
 
             # Save any attachments
             form.attach_proc.save_attachments(post)
@@ -590,6 +594,7 @@
                 post.user = request.user
                 post.user_ip = request.META.get("REMOTE_ADDR", "")
                 post.save()
+                notify_new_post(post)
 
                 # Save any attachments
                 form.attach_proc.save_attachments(post)
@@ -1102,6 +1107,7 @@
     if len(posts) > 0:
         new_topic = Topic(forum=new_forum, name=new_name, user=posts[0].user)
         new_topic.save()
+        notify_new_topic(new_topic)
         for post in posts:
             post.topic = new_topic
             post.save()
--- a/gpp/news/search_indexes.py	Sun Aug 07 03:38:42 2011 +0000
+++ b/gpp/news/search_indexes.py	Wed Aug 17 01:02:08 2011 +0000
@@ -1,7 +1,7 @@
 """Haystack search index for the news application."""
 from haystack.indexes import *
 from haystack import site
-from custom_search import CondQueuedSearchIndex
+from custom_search.indexes import CondQueuedSearchIndex
 
 from news.models import Story
 
--- a/gpp/podcast/search_indexes.py	Sun Aug 07 03:38:42 2011 +0000
+++ b/gpp/podcast/search_indexes.py	Wed Aug 17 01:02:08 2011 +0000
@@ -1,7 +1,7 @@
 """Haystack search index for the news application."""
 from haystack.indexes import *
 from haystack import site
-from custom_search import CondQueuedSearchIndex
+from custom_search.indexes import CondQueuedSearchIndex
 
 from podcast.models import Item
 
--- a/gpp/urls.py	Sun Aug 07 03:38:42 2011 +0000
+++ b/gpp/urls.py	Wed Aug 17 01:02:08 2011 +0000
@@ -7,7 +7,7 @@
 
 from news.feeds import LatestNewsFeed
 from forums.feeds import ForumsFeed
-from custom_search import CustomModelSearchForm
+from custom_search.forms import CustomModelSearchForm
 
 
 admin.autodiscover()
--- a/gpp/weblinks/search_indexes.py	Sun Aug 07 03:38:42 2011 +0000
+++ b/gpp/weblinks/search_indexes.py	Wed Aug 17 01:02:08 2011 +0000
@@ -1,7 +1,7 @@
 """Haystack search index for the weblinks application."""
 from haystack.indexes import *
 from haystack import site
-from custom_search import CondQueuedSearchIndex
+from custom_search.indexes import CondQueuedSearchIndex
 
 from weblinks.models import Link
 
--- a/gpp/ygroup/search_indexes.py	Sun Aug 07 03:38:42 2011 +0000
+++ b/gpp/ygroup/search_indexes.py	Wed Aug 17 01:02:08 2011 +0000
@@ -4,7 +4,7 @@
 """
 from haystack.indexes import *
 from haystack import site
-from custom_search import CondQueuedSearchIndex
+from custom_search.indexes import CondQueuedSearchIndex
 
 from ygroup.models import Post