【问题标题】:Django Haystack RealTimeSearchIndex on ManyToMany Relationships strange behaviour多对多关系上的 Django Haystack RealTimeSearchIndex 奇怪行为
【发布时间】:2011-12-30 15:49:11
【问题描述】:

related (as yet unanswered) question 之后,我做了一些调查,发现 Django Haystack 的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

果然,如果我检查对象,Django 还没有扩展模型以拥有related_field 字段。但是,如果我在显示视图时检查同一个对象,它确实有 related_field

总结

所以问题似乎在于,当 Haystack 运行其代码时,Django 将属性添加到 M2M 关系的反面的自动行为尚未发生。我怎样才能克服这个障碍,让 Haystack 的 RealTimeSearchIndex 也能更新相关字段的变化?

【问题讨论】:

    标签: django many-to-many django-haystack


    【解决方案1】:

    我认为最简单的解决方案是只使用内置的 RealTimeSearchIndex,并在你的 models.py 中添加一个信号监听器,以便在 m2m_changed 或任何时候重新索引模型。请参阅我对另一个问题的回答 - 您可以轻松地将其修改为索引 m2m_changed 而不是 post_save。

    【讨论】:

      【解决方案2】:

      刚刚尝试自己实现这个,你的问题是这一行中sender 参数的值:

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

      我阅读了documentation for the m2m_changed signal,发件人将类似于MyModel.my_field.through,因此您需要使用它。这意味着您不能像尝试那样拥有泛型类,但需要在每种情况下定义_setup_save 方法,并为模型具有的每个ManyToMany 字段连接m2m_changed 信号。

      例如,如果您的模型有两个 ManyToManyFields,分别称为区域和扇区,您可以这样做:

        # 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()

      【讨论】:

      • 感谢您的回答!几个月前我问过这个问题,所以我必须再次设置一个测试用例,但我基本上和你在答案中所做的完全一样,问题是 m2m 字段不存在反面(由 Django ORM 添加),我还需要更新该项目的索引。我没有做任何有趣的事情,比如动态添加它,而对register 的调用是在我定义了所有类之后。所以我实际上仍然不确定如何解决这个问题,但正如我所说,我必须在有时间的时候设置一个测试用例!
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-02
      • 1970-01-01
      • 2012-02-26
      • 1970-01-01
      相关资源
      最近更新 更多