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

问题描述

目前我看到两种可能性,在定义 SearchIndex 类后使用 >>>custom_uuid 'a3519262-72d6-40ce-8e49-f65e8637ec07' >>>"prefix_" + custom_uuid >>>'prefix_a3519262-72d6-40ce-8e49-f65e8637ec07' >>>'a3519262-72d6-40ce-8e49-f65e8637ec07' + "_suffix" >>>'a3519262-72d6-40ce-8e49-f65e8637ec07_suffix' 和使用 locals()

1.

setattr()

2.

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"})

我正在使用带有 ElasticSearch 的 Django-haystack

我知道使用 class TestIndex(indexes.SearchIndex,indexes.Indexable): pass for name in fields: setattr(JobTestIndex,"attr_%s" % name,DescriptionSearchField(boost=3,"name": "attr"})) setattr(JobTestIndex,"slug_%s" % name,DescriptionSearchField(**{"d_attr": name,"name": "slug"})) 不是最佳做法。

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

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

解决方法

我决定覆盖DeclarativeMetaclass__new__()方法,即SearchIndex的元类。

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


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,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],"d_attr": "text_description"})))
        for lang in settings.LANGUAGES
    )

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