动态添加字段到 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"]
。
目前我看到两种可能性,在定义 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"]
。