djangodjango-haystack

Django Haystack : Add data from prepared_field_name to the Indexing template


I am using templates to create the document which will be indexed, my template looks like, say:

{{object.generic_data}}

Now, i want my generic_data to be generated by a prepare_generic_data function . Doing this doesn't seem to work as the data is being fed to the template before the prepare function can return it seems.

So, I wanted to know if there is some way for me to use the template along side the prepare function or another way to get around this problem.

Also, please let me know if the question isn't clear enough. Edit:

Search_index

import datetime
from haystack import indexes
from diskus.models import Recipe,Post


class PostIndex(indexes.SearchIndex, indexes.Indexable):
    text = indexes.EdgeNgramField(document=True, use_template=True)
    post_id=indexes.IntegerField(model_attr='user_entity_id_id')
    content_key=indexes.IntegerField(model_attr='content_key')
    content_type=indexes.IntegerField(model_attr='content_type')
    generic_data=indexes.CharField()
    slug=indexes.CharField(model_attr='slug')

    def get_model(self):
        return Post

    def index_queryset(self, using=None):
        """Used when the entire index for model is updated."""
        return self.get_model().objects.all()

    def prepare_generic_data(self,obj):
        if obj.content_type==3:
            recipe=Recipe.objects.get(pk=obj.content_key)
            return recipe.name
        else:
            return "random_stuff"

Model:

class Post(UserEntity):
    user_entity_id = models.OneToOneField(UserEntity,
                              on_delete=models.CASCADE,
                              related_name='post',
                              primary_key=True,
                              db_column='id')
    content_key = models.IntegerField()
    content_type = models.IntegerField()

class Recipe(models.Model):
    id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=100)

Solution

  • In the context of an indexing template object is the model instance (a Post object), not a PostIndex object. So object has no generic_data property. You cannot access other index fields from inside the template.

    The simplest solution is to move the logic for generic_data into the Post model like so:

    class Post(UserEntity):
    
        def generic_data(self):
            if self.content_type == 3:
                # NOTE: you may need to ensure the Recipe is defined 
                # before Post in the models.py file, or you will get a name
                # resolution error.
                recipe = Recipe.objects.get(pk=self.content_key)
                return recipe.name
            else:
                return "random_stuff"
    

    Then the existing code in your template will work:

    {{ object.generic_data }}