annotate custom_search/signals.py @ 901:147a66da9cbc

Support development on mac.
author Brian Neal <bgneal@gmail.com>
date Sat, 07 Mar 2015 14:11:50 -0600
parents ad53d929281a
children
rev   line source
bgneal@753 1 """This module contains a custom Haystack signal processing class to update the
bgneal@753 2 search index in realtime. We update our search index by enqueuing edits and
bgneal@753 3 deletes into a queue for batch processing. Our class ensures we only enqueue
bgneal@753 4 content that should be in the search index.
bgneal@469 5
bgneal@469 6 """
bgneal@753 7 from django.db.models import signals
bgneal@753 8 import queued_search.signals
bgneal@469 9
bgneal@753 10 from bio.signals import profile_content_update
bgneal@753 11 from forums.signals import topic_content_update, post_content_update
bgneal@469 12
bgneal@753 13 import ygroup.models
bgneal@753 14 from weblinks.models import Link
bgneal@753 15 from podcast.models import Item
bgneal@753 16 from news.models import Story
bgneal@753 17 from downloads.models import Download
bgneal@753 18 from forums.models import Forum, Topic, Post
bgneal@753 19 from bio.models import UserProfile
bgneal@753 20
bgneal@753 21
bgneal@753 22 UID = 'custom_search.signals'
bgneal@753 23
bgneal@753 24
bgneal@753 25 class QueuedSignalProcessor(queued_search.signals.QueuedSignalProcessor):
bgneal@469 26 """
bgneal@753 27 This customized version of queued_search's QueuedSignalProcessor
bgneal@753 28 conditionally enqueues items to be indexed.
bgneal@469 29
bgneal@469 30 """
bgneal@753 31 def __init__(self, *args, **kwargs):
bgneal@753 32
bgneal@753 33 # We assume that it is okay to attempt to delete a model from the search
bgneal@753 34 # index even if the model object is not in the index. In other words,
bgneal@753 35 # attempting to delete an object from the index will not cause any
bgneal@753 36 # errors if it is not in the index. Thus if we see an object that has an
bgneal@753 37 # 'is_public' attribute, and it is false, we can safely enqueue a delete
bgneal@753 38 # in case the 'is_public' attribute just went from True to False. We
bgneal@753 39 # have no way of knowing that, it could have been False all along, but we
bgneal@753 40 # just try the delete in case to be safe.
bgneal@753 41
bgneal@753 42 # To make the code easier to read, use a table to drive our signal
bgneal@753 43 # connecting and disconnecting:
bgneal@753 44 self.signal_chain = [
bgneal@753 45 # Yahoo Group posts are always updated:
bgneal@753 46 (signals.post_save, ygroup.models.Post, self.enqueue_save),
bgneal@753 47 (signals.post_delete, ygroup.models.Post, self.enqueue_delete),
bgneal@753 48
bgneal@753 49 # Weblink Links are updated if they are public:
bgneal@753 50 (signals.post_save, Link, self.enqueue_public_save),
bgneal@753 51 (signals.post_delete, Link, self.enqueue_delete),
bgneal@753 52
bgneal@753 53 # Podcast Items are always updated:
bgneal@753 54 (signals.post_save, Item, self.enqueue_save),
bgneal@753 55 (signals.post_delete, Item, self.enqueue_delete),
bgneal@753 56
bgneal@753 57 # News Stories are always updated:
bgneal@753 58 (signals.post_save, Story, self.enqueue_save),
bgneal@753 59 (signals.post_delete, Story, self.enqueue_delete),
bgneal@753 60
bgneal@753 61 # Downloads are updated if they are public:
bgneal@753 62 (signals.post_save, Download, self.enqueue_public_save),
bgneal@753 63 (signals.post_delete, Download, self.enqueue_delete),
bgneal@753 64
bgneal@753 65 # Forum Topics are updated if they belong to a public forum:
bgneal@753 66 (topic_content_update, None, self.enqueue_topic_save),
bgneal@753 67 (signals.post_delete, Topic, self.enqueue_delete),
bgneal@753 68
bgneal@753 69 # Forum Posts are updated if they belong to a public forum:
bgneal@753 70 (post_content_update, None, self.enqueue_post_save),
bgneal@753 71 (signals.post_delete, Post, self.enqueue_delete),
bgneal@753 72
bgneal@753 73 # UserProfiles are updated when we receive a special signal:
bgneal@753 74 (profile_content_update, None, self.enqueue_profile),
bgneal@753 75 (signals.post_delete, UserProfile, self.enqueue_delete),
bgneal@753 76 ]
bgneal@753 77
bgneal@753 78 super(QueuedSignalProcessor, self).__init__(*args, **kwargs)
bgneal@753 79
bgneal@753 80 def setup(self):
bgneal@753 81 """We override setup() so we can attach signal handlers to only the
bgneal@753 82 models we search on. In some cases we have custom signals to tell us
bgneal@753 83 when to update the search index.
bgneal@469 84
bgneal@469 85 """
bgneal@753 86 for signal, sender, receiver in self.signal_chain:
bgneal@753 87 signal.connect(receiver, sender=sender, dispatch_uid=UID)
bgneal@469 88
bgneal@753 89 def teardown(self):
bgneal@753 90 """Disconnect all signals we previously connected."""
bgneal@753 91 for signal, sender, receiver in self.signal_chain:
bgneal@753 92 signal.disconnect(receiver, sender=sender, dispatch_uid=UID)
bgneal@753 93
bgneal@753 94 def enqueue_public_save(self, sender, instance, **kwargs):
bgneal@753 95 """Index only if the instance is_public.
bgneal@753 96
bgneal@753 97 If not, enqueue a delete just in case the is_public flag got flipped
bgneal@753 98 from True to False.
bgneal@469 99
bgneal@469 100 """
bgneal@753 101 if instance.is_public:
bgneal@753 102 self.enqueue_save(sender, instance, **kwargs)
bgneal@753 103 else:
bgneal@753 104 self.enqueue_delete(sender, instance, **kwargs)
bgneal@677 105
bgneal@753 106 def enqueue_topic_save(self, sender, **kwargs):
bgneal@753 107 """Enqueue only if the topic instance belongs to a public forum."""
bgneal@753 108 if sender.forum.id in Forum.objects.public_forum_ids():
bgneal@753 109 self.enqueue_save(Topic, sender, **kwargs)
bgneal@677 110
bgneal@753 111 def enqueue_post_save(self, sender, **kwargs):
bgneal@753 112 """Enqueue only if the post instance belongs to a public forum."""
bgneal@753 113 if sender.topic.forum.id in Forum.objects.public_forum_ids():
bgneal@753 114 self.enqueue_save(Post, sender, **kwargs)
bgneal@677 115
bgneal@753 116 def enqueue_profile(self, sender, **kwargs):
bgneal@753 117 """Forward the user profile instance on unconditionally."""
bgneal@753 118 self.enqueue_save(UserProfile, sender, **kwargs)