动态添加字段到 SearchIndex (django-haystack)

add fields to SearchIndex dynamically (django-haystack)

目前我看到两种可能性,在定义 SearchIndex class:

之后使用 locals() 和使用 setattr()

1.

class TestIndex(indexes.SearchIndex, indexes.Indexable):
    for name in fields:
        locals()["attr_%s" % name] = DescriptionSearchField(boost=3, **{"d_attr": name, "name": "attr"})
        locals()["slug_%s" % name] = DescriptionSearchField(**{"d_attr": name, "name": "slug"})

2.


class TestIndex(indexes.SearchIndex, indexes.Indexable):
    pass

for name in fields:
    setattr(JobTestIndex, "attr_%s" % name, DescriptionSearchField(boost=3, **{"d_attr": name, "name": "attr"}))
    setattr(JobTestIndex, "slug_%s" % name, DescriptionSearchField(**{"d_attr": name, "name": "slug"}))

我正在使用 Django-haystack 和 ElasticSearch

我知道使用 locals() 不是最佳做法。

那么解决我的问题的正确方法是什么?

非常感谢任何建议。谢谢。

我决定覆盖 DeclarativeMetaclass, that is the metaclass of SearchIndex__new__() 方法。

所以这部分代码现在看起来像这样:


from haystack import indexes

from django.utils import six

from search_fields import DescriptionSearchField


class ChildDeclarativeMetaclass(indexes.DeclarativeMetaclass):
    def __new__(cls, name, bases, attrs):
        for f in reversed(attrs.pop("_extra_fields")):
            attrs.update(f)
        return super(ChildDeclarativeMetaclass, cls).__new__(cls, name, bases, attrs)


class OpenTaskIndex(six.with_metaclass(ChildDeclarativeMetaclass, indexes.SearchIndex, indexes.Indexable)):
    text = indexes.CharField(document=True, use_template=True, template_name='search/indexes/job/open_task_text.txt')
   
    _extra_fields = tuple((
        ("title_%s" % lang[0], DescriptionSearchField(boost=3, **{"d_lang": lang[0], "d_attr": "title"})),
        ("slug_%s" % lang[0], DescriptionSearchField(**{"d_lang": lang[0], "d_attr": "slug"})),
        ("text_%s" % lang[0], DescriptionSearchField(**{"d_lang": lang[0], "d_attr": "text_description"})))
        for lang in settings.LANGUAGES
    )

如果您在 class 创建之后设置字段。它们不会添加到 DeclarativeMetaclass 中的 attrs["fields"]