Mercurial > public > sg101
view custom_search/signals.py @ 822:2c4f28b1c12a
Band map WIP: update admin dashboard for new band map entries.
author | Brian Neal <bgneal@gmail.com> |
---|---|
date | Wed, 24 Sep 2014 19:53:36 -0500 |
parents | ad53d929281a |
children |
line wrap: on
line source
"""This module contains a custom Haystack signal processing class to update the search index in realtime. We update our search index by enqueuing edits and deletes into a queue for batch processing. Our class ensures we only enqueue content that should be in the search index. """ from django.db.models import signals import queued_search.signals from bio.signals import profile_content_update from forums.signals import topic_content_update, post_content_update import ygroup.models from weblinks.models import Link from podcast.models import Item from news.models import Story from downloads.models import Download from forums.models import Forum, Topic, Post from bio.models import UserProfile UID = 'custom_search.signals' class QueuedSignalProcessor(queued_search.signals.QueuedSignalProcessor): """ This customized version of queued_search's QueuedSignalProcessor conditionally enqueues items to be indexed. """ def __init__(self, *args, **kwargs): # We assume that it is okay to attempt to delete a model from the search # index even if the model object is not in the index. In other words, # attempting to delete an object from the index will not cause any # errors if it is not in the index. Thus if we see an object that has an # 'is_public' attribute, and it is false, we can safely enqueue a delete # in case the 'is_public' attribute just went from True to False. We # have no way of knowing that, it could have been False all along, but we # just try the delete in case to be safe. # To make the code easier to read, use a table to drive our signal # connecting and disconnecting: self.signal_chain = [ # Yahoo Group posts are always updated: (signals.post_save, ygroup.models.Post, self.enqueue_save), (signals.post_delete, ygroup.models.Post, self.enqueue_delete), # Weblink Links are updated if they are public: (signals.post_save, Link, self.enqueue_public_save), (signals.post_delete, Link, self.enqueue_delete), # Podcast Items are always updated: (signals.post_save, Item, self.enqueue_save), (signals.post_delete, Item, self.enqueue_delete), # News Stories are always updated: (signals.post_save, Story, self.enqueue_save), (signals.post_delete, Story, self.enqueue_delete), # Downloads are updated if they are public: (signals.post_save, Download, self.enqueue_public_save), (signals.post_delete, Download, self.enqueue_delete), # Forum Topics are updated if they belong to a public forum: (topic_content_update, None, self.enqueue_topic_save), (signals.post_delete, Topic, self.enqueue_delete), # Forum Posts are updated if they belong to a public forum: (post_content_update, None, self.enqueue_post_save), (signals.post_delete, Post, self.enqueue_delete), # UserProfiles are updated when we receive a special signal: (profile_content_update, None, self.enqueue_profile), (signals.post_delete, UserProfile, self.enqueue_delete), ] super(QueuedSignalProcessor, self).__init__(*args, **kwargs) def setup(self): """We override setup() so we can attach signal handlers to only the models we search on. In some cases we have custom signals to tell us when to update the search index. """ for signal, sender, receiver in self.signal_chain: signal.connect(receiver, sender=sender, dispatch_uid=UID) def teardown(self): """Disconnect all signals we previously connected.""" for signal, sender, receiver in self.signal_chain: signal.disconnect(receiver, sender=sender, dispatch_uid=UID) def enqueue_public_save(self, sender, instance, **kwargs): """Index only if the instance is_public. If not, enqueue a delete just in case the is_public flag got flipped from True to False. """ if instance.is_public: self.enqueue_save(sender, instance, **kwargs) else: self.enqueue_delete(sender, instance, **kwargs) def enqueue_topic_save(self, sender, **kwargs): """Enqueue only if the topic instance belongs to a public forum.""" if sender.forum.id in Forum.objects.public_forum_ids(): self.enqueue_save(Topic, sender, **kwargs) def enqueue_post_save(self, sender, **kwargs): """Enqueue only if the post instance belongs to a public forum.""" if sender.topic.forum.id in Forum.objects.public_forum_ids(): self.enqueue_save(Post, sender, **kwargs) def enqueue_profile(self, sender, **kwargs): """Forward the user profile instance on unconditionally.""" self.enqueue_save(UserProfile, sender, **kwargs)