Skip to content

Commit ea5dbd5

Browse files
committed
Fixed a bug where South would cause Haystack to setup too soon. Thanks to adamfast for the report!
1 parent b6c5a0e commit ea5dbd5

File tree

1 file changed

+38
-2
lines changed

1 file changed

+38
-2
lines changed

haystack/models.py

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# "Hey, Django! Look at me, I'm an app! For Serious!"
22
import logging
3+
from django.conf import settings
34
from django.core.exceptions import ObjectDoesNotExist
45
from django.db import models
56
from django.utils.encoding import force_unicode
@@ -221,11 +222,46 @@ def __setstate__(self, data_dict):
221222

222223
# Setup pre_save/pre_delete signals to make sure things like the signals in
223224
# ``RealTimeSearchIndex`` are setup in time to handle data changes.
224-
def load_indexes(sender, instance, *args, **kwargs):
225+
def load_indexes(sender, *args, **kwargs):
225226
from haystack import connections
226227

227228
for conn in connections.all():
228-
conn.get_unified_index().setup_indexes()
229+
ui = conn.get_unified_index()
230+
ui.setup_indexes()
231+
232+
233+
def reload_indexes(sender, *args, **kwargs):
234+
from haystack import connections
235+
236+
for conn in connections.all():
237+
ui = conn.get_unified_index()
238+
# Note: Unlike above, we're resetting the ``UnifiedIndex`` here.
239+
# Thi gives us a clean slate.
240+
ui.reset()
241+
ui.setup_indexes()
242+
229243

230244
models.signals.pre_save.connect(load_indexes, dispatch_uid='setup_index_signals')
231245
models.signals.pre_delete.connect(load_indexes, dispatch_uid='setup_index_signals')
246+
247+
248+
if 'south' in settings.INSTALLED_APPS:
249+
# South causes a little mayhem, as when you run a ``syncdb``, it'll setup
250+
# the apps *without* migrations using Django's built-in ``syncdb``. When
251+
# this happens, ``INSTALLED_APPS`` consists of only those apps, NOT all
252+
# apps.At the end of that sync, Django runs ``create_permissions``, which
253+
# of course uses the ORM, causing the ``pre_save`` above to fire.
254+
255+
# The effect is that Haystack runs its setup against the then-subset of
256+
# ``INSTALLED_APPS``. Once that's done, it won't re-setup the
257+
# ``UnifiedIndex`` again, since the signal has a ``dispatch_uid``.
258+
259+
# This bug gets exposed only either when people run tests that *use*
260+
# the South migrations OR when they have a data migration & the changed
261+
# data isn't picked up by ``RealTimeSearchIndex`` (or similar).
262+
263+
# In the event of this, the only safe route is to listen for
264+
# ``south.signals.post_migrate``, then re-run setup. This will
265+
# unfortunately happen per-app, but should be quick & reliable.
266+
from south.signals import post_migrate
267+
post_migrate.connect(reload_indexes)

0 commit comments

Comments
 (0)