How to make an abstract Haystack SearchIndex class
Asked Answered
K

2

7

How do you make an abstract SearchIndex class, similar to how Django lets you make abstract base models?

I have several SearchIndexes that I'd like to give the same basic fields (object_id, timestamp, importance, etc). Currently, I'm duplicating all this code, so I'm trying to create a "BaseIndex" and simply have all the real index classes inherit from this.

I'm tried:

class BaseIndex(indexes.SearchIndex, indexes.Indexable):
    text = indexes.CharField(document=True, use_template=True)
    object_id = indexes.IntegerField()
    timestamp = indexes.DateTimeField()

    class Meta:
        abstract = True

class PersonIndex(BaseIndex):
    ...other fields...

but this gives me the error:

NotImplementedError: You must provide a 'model' method for the '<myapp.search_indexes.BaseIndex object at 0x18a7328>' index.

so I then tried:

class BaseIndex(object):
    text = indexes.CharField(document=True, use_template=True)
    object_id = indexes.IntegerField()
    timestamp = indexes.DateTimeField()

class PersonIndex(BaseIndex, indexes.SearchIndex, indexes.Indexable):
    first_name = indexes.CharField()
    middle_name = indexes.CharField()
    last_name = indexes.CharField()

but these gives me error:

SearchFieldError: The index 'PersonIndex' must have one (and only one) SearchField with document=True.

How do I inherit from a custom SearchIndex subclass?

Kathie answered 3/6, 2013 at 15:14 Comment(1)
A search indexes Meta class doesn't have an attribute abstract... Don't know where you got that from?Lousewort
J
13

Just don't include indexes.Indexable as a parent on anything you don't want indexing.

So modifying your first example.

class BaseIndex(indexes.SearchIndex):
    text = indexes.CharField(document=True, use_template=True)
    object_id = indexes.IntegerField()
    timestamp = indexes.DateTimeField()

    class Meta:
        abstract = True

class PersonIndex(BaseIndex, indexes.Indexable):
    ...other fields...
Jobi answered 4/6, 2013 at 9:2 Comment(4)
This worked for me. I do not believe you need the class Meta: abstract = True bit for it to work.Sturdivant
abstract = True is useful if you want to stop other developers trying to use your class directly.Jobi
actually, that's for django models, for Indexes it doesn't seem to work, I probably just copied it from the question.Jobi
Sorry, I should have included that in my comment that it's not necessary for haystack indexes. But the answer helped me regardless. Thanks!Sturdivant
A
4
class BaseIndex(indexes.SearchIndex):
    model=None        

    text = indexes.CharField(document=True, use_template=True)
    object_id = indexes.IntegerField()
    timestamp = indexes.DateTimeField()

    def get_model(self):
        return self.model

class PersonIndex(BaseIndex, indexes.Indexable):
    first_name = indexes.CharField()
    middle_name = indexes.CharField()
    last_name = indexes.CharField()

    def get_model(self):
        return Person
Abet answered 23/1, 2014 at 9:37 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.