以编程方式创建 haystack 索引

Programmatically create haystack index

创建 Haystack 搜索索引的标准方法是在 search_indexes.py 文件中,每个模型有 class 个索引,如下所示:

class FooIndex(indexes.Indexable):
    def get_model(self):
        return models.Foo

但是,我有很多模型,它们的行为都相似,我想为它们编制索引(以及以其他方式注册)。

例如,给定此 models.py 代码:

class BaseModel(models.model):
   class Meta:
       abstract = True
   # some shared fields
class Foo(BaseModel):
  pass # some different fields
class Bar(BaseModel):
  pass

此代码有效:

def register_base_model(sub_class, *args, **kwargs):
    #other shared actions here
    admin.site.register(sub_class,BaseAdmin) # BaseAdmin defined elsewhere
register_base_model(models.Foo)

但这不会:

def register_base_model(sub_class, *args, **kwargs):
    #other shared actions here
    admin.site.register(sub_class,BaseAdmin) # BaseAdmin defined elsewhere
    class SubclassedIndex(indexes.SearchIndex,indexes.Indexable):
        def get_model(self):
            return sub_class

register_base_model(models.Foo)

因为classSubclassedIndex只在register_base_model的范围内。 Haystack 1.x 曾经有一个 register/unregister API,但现在没有了,虽然新方法更简单,但我需要类似的行为。

如何以编程方式注册 HaystackIndex,而不依赖于它现在运行的自动方式?

这至少可以通过一种方式完成,尽管是以一种非常 的方式。

首先,您必须有一个带有 search_indexes.py 模块的应用程序,并且必须在您以编程方式添加索引的地方导入它:

from haystack import connections
from haystack.constants import DEFAULT_ALIAS

import my_app.search_indexes as search_index

for my_class in some_list_of_models:

    search_index_class_name = "%s_%sSearchIndex"%(concept_class._meta.app_label,concept_class.__name__)

    # Create a new subclass of search index (see below)
    # And monkey-patch it in.
    setattr(search_index, class_name, create(concept_class))

# Since we've added a new class, kill the index so it is rebuilt next time we access the index.
connections[DEFAULT_ALIAS]._index = None

然后你需要一个函数来构建 class

def create(cls):
    class DynamicSearchIndex(indexes.SearchIndex, indexes.Indexable):
        # What ever fields are needed go here
        def get_model(self):
            return cls
    return SubclassedConceptIndex

正如我发现的那样,您需要确保模板存在于正确的位置,并且可能需要添加一个 try/except 包装器以在构建 [=25= 时捕获错误]es.