Cristian Rojas
Cristian Rojas

Reputation: 2862

Django how to get haystack working with django-hvad

I'm working on a multilingual application where I need to implement a search engine, I opted for haystack.

This is the model I want to index

class Post(TranslatableModel):
    category = models.ForeignKey(
        Category,
        related_name='posts',
        verbose_name=_(u'Categoría')
    )
    slug = AutoSlugField(
        populate_from='title'
    )
    featured_picture = ThumbnailerImageField(
        upload_to='blog/posts/featured-pictures',
        verbose_name=_(u'Imagen destacada'),
        help_text=_(u'Tamaño: 850 x 423px. Será recordada si no.')
    )
    box_bg = models.CharField(
        max_length=20,
        verbose_name=_(u'Color de fondo de la caja'),
        choices=SERVICE_BOX_COLORS,
        # Could be an image
        null=True, blank=True
    )
    box_image_bg = ThumbnailerImageField(
        upload_to='blog/posts/background-images',
        verbose_name=_(u'Imagen de fondo de la caja'),
        null=True, blank=True,
        help_text=_(u'Tamaño: 500 x 500px. Será recordada si no.')
    )

    translations = TranslatedFields(
        title=models.CharField(
            max_length=100,
            verbose_name=_(u'Título')
        ),
        content=RichTextField(
            verbose_name=_(u'Contenido')
        ),
        meta_description=models.TextField(
            verbose_name=_(u'Meta description (SEO)'),
            help_text=_(u'Máximo 160 caracteres.'),
            max_length=160
        )
    )

I don't know in haystack how to deal with hvad translation fields

Upvotes: 1

Views: 295

Answers (1)

Roodie
Roodie

Reputation: 247

I will describe what I did when faced a similar problem.

In your index definition, specify a field for the current language. Django-hvad always returns a 'language_code' field if you do a query, so for example:

 class PostIndex(indexes.SearchIndex, indexes.Indexable):
     # your field definitions here
     lan = indexes.CharField(model_attr='language_code')

     # rest of your configuration here

     def index_queryset(self, using=None):
         return self.get_model().objects.language('all').all()

     def read_queryset(self, using=None):
         return self.get_model().objects.language()

This way when Haystack indexes the Posts, it will get every language version separately and store it along with a language code.

You will have to modify your search form to include the lan field as a filter:

class PostSearchForm(SearchForm):
    lan = forms.CharField(required=False)

    def search(self):
        sqs = super(PostSearchForm, self).search()
        if not self.is_valid():
            return self.no_query_found()
        if self.cleaned_data.get('lan'):
            sqs = sqs.filter(lan=self.cleaned_data['lan'])
        return sqs

It can be a hidden input field, with the value taken from request.LANGUAGE_CODE.

Upvotes: 6

Related Questions