]> git.parisson.com Git - telemeta.git/commitdiff
Optimization of RealTimeCustomSIgnal
authormathieu <mathieu.boye28@gmail.com>
Mon, 11 Jul 2016 09:31:54 +0000 (11:31 +0200)
committermathieu <mathieu.boye28@gmail.com>
Mon, 11 Jul 2016 09:31:54 +0000 (11:31 +0200)
Modify methods of Signal
Add routers

app/settings.py
telemeta/search_indexes.py
telemeta/util/search_router.py [new file with mode: 0644]
telemeta/util/search_signals.py

index 762764eb87e00c993237039dca832c36fe53dafe..88847ef63946d05aabf82f4e6f73f23ee69483cb 100644 (file)
@@ -330,8 +330,9 @@ HAYSTACK_CONNECTIONS = {
     },
 }
 
-HAYSTACK_SIGNAL_PROCESSOR = 'haystack.signals.RealtimeSignalProcessor'
-# HAYSTACK_SIGNAL_PROCESSOR = 'telemeta.util.search_signals.RealTimeCustomSignal'
+HAYSTACK_ROUTERS = ['telemeta.util.search_router.AutoRouter', 'haystack.routers.DefaultRouter']
+# HAYSTACK_SIGNAL_PROCESSOR = 'haystack.signals.RealtimeSignalProcessor'
+HAYSTACK_SIGNAL_PROCESSOR = 'telemeta.util.search_signals.RealTimeCustomSignal'
 HAYSTACK_SEARCH_RESULTS_PER_PAGE = 50
 
 BOWER_COMPONENTS_ROOT = '/srv/bower/'
index d3aa087817f7ca923ca064700a4046c7067a08b5..c49497898a3bb8ba53bf4e85e1de1d2149f64aeb 100644 (file)
@@ -248,8 +248,10 @@ class LocationIndex(indexes.SearchIndex, indexes.Indexable):
         return Location
 
     def index_queryset(self, using=None):
-        return MediaItem.objects.all().locations()
-
+        loc = MediaItem.objects.values('location')
+        old = Location.objects.filter(current_location__in=loc).values('id')
+        anc = LocationRelation.objects.filter(location__in=loc).values('ancestor_location')
+        return Location.objects.filter(Q(pk__in=loc)|Q(pk__in=old)|Q(pk__in=anc))
 
 class LocationAliasIndex(indexes.SearchIndex, indexes.Indexable):
 
diff --git a/telemeta/util/search_router.py b/telemeta/util/search_router.py
new file mode 100644 (file)
index 0000000..3f3f60f
--- /dev/null
@@ -0,0 +1,15 @@
+from haystack.routers import BaseRouter
+from telemeta.models.instrument import Instrument, InstrumentAlias
+from telemeta.models.location import LocationAlias, Location
+
+#Router in order to determine
+#that autocomplete data are stored in "autocomplete" index
+class AutoRouter(BaseRouter):
+
+    def for_write(self, **hints):
+        obj = hints.get('instance')
+        if isinstance(obj, Instrument) or isinstance(obj, InstrumentAlias) or isinstance(obj, Location) \
+                or isinstance(obj, LocationAlias):
+            return 'autocomplete'
+        else:
+            return None
\ No newline at end of file
index cf96b3f2775012c14e026116d7e00fa419ddc408..f37107949f49aebed131c9a751840dd42e00f807 100644 (file)
@@ -1,74 +1,78 @@
-from django.db import models
-from haystack import signals
 from telemeta.models import *
-from telemeta.search_indexes import *
+from haystack import signals
+from django.db.models.signals import post_save, post_delete, pre_delete
 from django.db.models import Q
 
-#Custom realtime signal in order to update the "autcomplete" index
+#Custom realtime signal in order to update the "autocomplete" index
 #when add/remove instruments/locations in items.
 #Differences of values of fields are checked by the tracker
 #of django-dirtyfields' module
 class RealTimeCustomSignal(signals.RealtimeSignalProcessor):
-    handleFields = ('location', 'instrument', 'alias')
-    handleModels = (MediaItem, MediaItemPerformance, )
+
+    sender_auto_only = (Instrument, InstrumentAlias, Location, LocationAlias)
 
     def __init__(self, *args, **kwargs):
         super(RealTimeCustomSignal, self).__init__(*args, **kwargs)
-        self.update_fields = []
-
-    def post_save_location(self, object):
-        id = object.get_dirty_fields(check_relationship=True).get('location')
-        locs = Location.objects.filter(Q(pk=id) | Q(past_names__pk=id) | Q(descendant_relations__location__pk=id))
-        localias = LocationAlias.objects.filter(location__id=id)
-        for loc in locs:
-            LocationIndex().remove_object(instance=loc, using='autocomplete')
-        for loc in localias:
-            LocationAliasIndex().remove_object(instance=loc, using='autocomplete')
-        if object.location is not None:
-            locs = MediaItem.objects.filter(id=object.id).locations()
-            localias = LocationAlias.objects.filter(location__pk=object.location.id)
-            for loc in locs:
-                LocationIndex().update_object(instance=loc, using='autocomplete')
-            for loc in localias:
-                LocationAliasIndex().update_object(instance=loc, using='autocomplete')
-
-
-    def post_save_instrument(self, object):
-        id = object.get_dirty_fields(check_relationship=True).get('instrument')
-        if id is not None:
-             instru = Instrument.objects.get(pk=id)
-             InstrumentIndex().remove_object(instance=instru, using='autocomplete')
-        if object.instrument is not None:
-            newinstru = Instrument.objects.get(id=object.instrument.id)
-            InstrumentIndex().update_object(instance=newinstru, using='autocomplete')
 
-    def post_save_alias(self, object):
-        id = object.get_dirty_fields(check_relationship=True).get('alias')
-        if id is not None:
-             alias = InstrumentAlias.objects.get(pk=id)
-             InstrumentAliasIndex().remove_object(instance=alias, using='autocomplete')
-        if object.alias is not None:
-            newalias = InstrumentAlias.objects.get(id=object.alias.id)
-            InstrumentAliasIndex().update_object(instance=newalias, using='autocomplete')
+    def update_instrument(self, instance, old_value):
+        if instance is not None and instance.instrument is not None:
+            post_save.send(sender=Instrument, instance=instance.instrument, in_real_signal=True)
+        if old_value is not None:
+            instru = Instrument.objects.get(id=old_value) if not isinstance(old_value, Instrument) else old_value
+            nb = instru.performances.count()
+            if nb == 0:
+                post_delete.send(sender=Instrument, instance=instru)
 
-    def handle_pre_save(self, sender, instance, **kwargs):
-        if sender in self.handleModels and instance.is_dirty(check_relationship=True):
-            for field in instance.get_dirty_fields(check_relationship=True).keys():
-                if field in self.handleFields:
-                    self.update_fields.append(field)
+    def update_alias(self, instance, old_value):
+        if instance is not None and instance.alias is not None:
+            post_save.send(sender=InstrumentAlias, instance=instance.alias, in_real_signal=True)
+        if old_value is not None:
+            alias = InstrumentAlias.objects.get(id=old_value) if not isinstance(old_value, InstrumentAlias) else old_value
+            nb = alias.performances.count()
+            if nb == 0:
+                post_delete.send(sender=InstrumentAlias, instance=alias)
 
-    def handle_pre_delete(self, sender, instance, **kwargs):
-        InstrumentIndex().remove_object(instance=instance.instrument, using='autocomplete')
-        InstrumentAliasIndex().remove_object(instance=instance.alias, using='autocomplete')
+    def update_location(self, instance, old_value):
+        if instance is not None and instance.location is not None:
+            loc = Location.objects.filter(Q(current_location=instance.location)|Q(descendant_relations__location=instance.location))
+            localias = LocationAlias.objects.filter(location=instance.location)
+            post_save.send(sender=Location, instance=instance.location, in_real_signal=True)
+            for l in loc:
+                post_save.send(sender=Location, instance=l, in_real_signal=True)
+            for l in localias:
+                post_save.send(sender=LocationAlias, instance=l, in_real_signal=True)
+        if old_value is not None:
+            location = Location.objects.get(id=old_value) if not isinstance(old_value, Location) else old_value
+            loc = Location.objects.filter(Q(current_location=location) | Q(descendant_relations__location=location))
+            can_delete_alias = post_delete.send(sender=Location, instance=location, in_real_signal=True)[0][1]
+            for l in loc:
+                post_delete.send(sender=Location, instance=l, in_real_signal=True)
+            if can_delete_alias:
+                localias = LocationAlias.objects.filter(location=location)
+                for l in localias:
+                     post_delete.send(sender=LocationAlias, instance=l, in_real_signal=True)
 
     def handle_save(self, sender, instance, **kwargs):
-        if sender in self.handleModels:
-            for field in self.update_fields:
-                getattr(self, "post_save_%s" % field)(instance)
-        del self.update_fields[:]
-        super(RealTimeCustomSignal, self).handle_save(sender, instance, **kwargs)
+        if sender == MediaItemPerformance or sender == MediaItem:
+            df = instance.get_dirty_fields(check_relationship=True)
+            if df.has_key('instrument'):
+                self.update_instrument(instance, df.get('instrument'))
+            if df.has_key('alias'):
+                self.update_alias(instance, df.get('alias'))
+            if df.has_key('location'):
+                self.update_location(instance, df.get('location'))
+        if kwargs.get('in_real_signal', False) or sender not in self.sender_auto_only:
+             super(RealTimeCustomSignal, self).handle_save(sender, instance, **kwargs)
 
-    def setup(self):
-        super(RealTimeCustomSignal, self).setup()
-        models.signals.pre_save.connect(self.handle_pre_save)
-        models.signals.pre_delete.connect(self.handle_pre_delete, sender=MediaItemPerformance)
+    def handle_delete(self, sender, instance, **kwargs):
+        if sender == MediaItemPerformance:
+            self.update_instrument(instance=None, old_value=instance.instrument)
+            self.update_alias(instance=None, old_value=instance.alias)
+        elif sender == MediaItem:
+            self.update_location(instance=None, old_value=instance.location)
+        elif sender == Location:
+            l = Location.objects.filter(Q(past_names=instance)|Q(ancestor_relations__ancestor_location=instance)|Q(id=instance.id))
+            if l.count() != 0 and l.filter(mediaitem__isnull=False).exists():
+                return False
+        super(RealTimeCustomSignal, self).handle_delete(sender=sender, instance=instance, **kwargs)
+        return True
\ No newline at end of file