6. Search and the Django-CMS

Currently the best way to integrate search with the Django-CMS is Haystack, however it is not officially supported.

6.1. Haystack

If you go the Haystack way, you’ll need a search_indexes.py. Haystack doesn’t care if it’s in the same app as the models, so you can put it into any app within your project.

Here is an example untested and unsupported search_indexes.py:

  1. from django.conf import settings
  2. from django.utils.translation import string_concat, ugettext_lazy
  3. from haystack import indexes, site
  4. from cms.models.managers import PageManager
  5. from cms.models.pagemodel import Page
  6. def page_index_factory(lang, lang_name):
  7. if isinstance(lang_name, basestring):
  8. lang_name = ugettext_lazy(lang_name)
  9. def get_absolute_url(self):
  10. return '/%s%s' % (lang, Page.get_absolute_url(self))
  11. class Meta:
  12. proxy = True
  13. app_label = 'cms'
  14. verbose_name = string_concat(Page._meta.verbose_name, ' (', lang_name, ')')
  15. verbose_name_plural = string_concat(Page._meta.verbose_name_plural, ' (', lang_name, ')')
  16. attrs = {'__module__': Page.__module__,
  17. 'Meta': Meta,
  18. 'objects': PageManager(),
  19. 'get_absolute_url': get_absolute_url}
  20. _PageProxy = type("Page%s" % lang.title() , (Page,), attrs)
  21. _PageProxy._meta.parent_attr = 'parent'
  22. _PageProxy._meta.left_attr = 'lft'
  23. _PageProxy._meta.right_attr = 'rght'
  24. _PageProxy._meta.tree_id_attr = 'tree_id'
  25. class _PageIndex(indexes.SearchIndex):
  26. language = lang
  27. text = indexes.CharField(document=True, use_template=False)
  28. pub_date = indexes.DateTimeField(model_attr='publication_date')
  29. login_required = indexes.BooleanField(model_attr='login_required')
  30. url = indexes.CharField(stored=True, indexed=False, model_attr='get_absolute_url')
  31. title = indexes.CharField(stored=True, indexed=False, model_attr='get_title')
  32. def prepare(self, obj):
  33. self.prepared_data = super(_PageIndex, self).prepare(obj)
  34. plugins = obj.cmsplugin_set.filter(language=lang)
  35. text = ''
  36. for plugin in plugins:
  37. instance, _ = plugin.get_plugin_instance()
  38. if hasattr(instance, 'search_fields'):
  39. text += ''.join(getattr(instance, field) for field in instance.search_fields)
  40. self.prepared_data['text'] = text
  41. return self.prepared_data
  42. def get_queryset(self):
  43. return _PageProxy.objects.published().filter(title_set__language=lang, publisher_is_draft=False).distinct()
  44. return _PageProxy, _PageIndex
  45. for lang_tuple in settings.LANGUAGES:
  46. lang, lang_name = lang_tuple
  47. site.register(*page_index_factory(lang, lang_name))