Django Haystack RealTimeSearchIndex на многие отношения Многие странное поведение - PullRequest
2 голосов
/ 30 декабря 2011

После связанного (пока еще без ответа) вопроса я провел некоторое исследование и обнаружил, что текущая реализация RealTimeSearchIndex Джанго Хейстека не предпринимает попыток также обновлять изменения в смежных областях (от многих к многим).,Я думал, что это будет легко исправить - в конце концов, я мог бы просто расширить RealTimeSearchIndex следующим образом:

class RealTimeM2MSearchIndex(RealTimeSearchIndex):
    def _setup_save(self, model):
        signals.m2m_changed.connect(self.update_object, sender=model)
        signals.post_save.connect(self.update_object, sender=model)

Но потом я понял (или, по крайней мере, предположил, что это не работает), что это работает толькоесли поле M2M определено в самой модели, а не если это «обратная» сторона отношения M2M.Пытаясь это исправить, я затем сделал что-то вроде следующего:

        signals.m2m_changed.connect(self.update_object, sender=model.related_field.through)

Где related_field - это название конкретной Модели на другой стороне определения ManyToMany.Как ни странно, после запуска Django жалуется, что у модели нет такого поля, related_field.

И, конечно же, если я осматриваю объект, Джанго еще не расширил модель, чтобы иметь поле related_field.Однако, если я проверяю тот же объект при отображении вида, он имеет related_field.

Сводка

Таким образом, проблема заключается в том, что автоматическое поведение Django для добавления атрибута в обратную сторону отношения M2M еще не произошло, когда Haystack запускает свой код.Как я могу преодолеть это препятствие и позволить Haystack's RealTimeSearchIndex также обновлять связанные изменения поля?

Ответы [ 2 ]

0 голосов
/ 21 июня 2012

Только что попытался реализовать это сам, и ваша проблема в значении аргумента sender в этой строке:

signals.m2m_changed.connect(self.update_object, sender=model)

Я прочитал документацию для сигнала m2m_changed , и отправитель будет выглядеть как MyModel.my_field.through, так что вам нужно это использовать. Это означает, что у вас не может быть универсального класса, как вы пытаетесь сделать, но вам нужно будет определить метод _setup_save в каждом случае с сигналом m2m_changed, подключенным для каждого поля ManyToMany, которое есть в модели.

Например, если ваша модель имеет два поля ManyToManyField, называемых region и sector, вы можете сделать:

  # we implement these to force the update when the ManyToMany fields change
  def _setup_save(self, model):
      signals.m2m_changed.connect(self.update_object,
              sender=MyModel.sector.through)
      signals.m2m_changed.connect(self.update_object,
              sender=MyModel.region.through)
      signals.post_save.connect(self.update_object, sender=model)

Вы также должны определить метод _teardown_save():

  def _teardown_save(self, model):
      signals.m2m_changed.disconnect(self.update_object,
              sender=MyModel.sector.through)
      signals.m2m_changed.disconnect(self.update_object,
              sender=MyModel.region.through)
      signals.post_save.disconnect(self.update_object, sender=model)

(Это основано на коде, который я тестировал, похоже, он работает - конечно, нет ошибок в отношении несуществующих полей).

Обновление: Просто прочитайте ваш вопрос более внимательно. Возможно ли, что ваша модель имеет динамическое добавление ManyToManyField? Вызов register() после того, как вы определили все свои классы?

0 голосов
/ 29 марта 2012

Я думаю, что самое простое решение - просто использовать встроенный RealTimeSearchIndex и добавить прослушиватель сигналов в вашем models.py для переиндексации модели в m2m_changed или в любое время. Смотрите мой ответ на другой вопрос - вы можете легко изменить его на индекс m2m_changed вместо post_save.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...