django-cms-facetsearch

This package provides multilingual search indexes for easy Haystack integration with django CMS.

Usage

After installing django-cms-facetsearch through your package manager of choice, add cms_facetsearch to your INSTALLED_APPS. That’s it.

For setting up Haystack using solr as needed for faceting, please refer to their documentation.

Customizing the Index

You can customize what parts of a CMSPlugin end up in the index with two class attributes on CMSPlugin subclasses:

search_fields

a list of field names to index.

search_fulltext

if True, the index renders the plugin and adds the result (sans HTML tags) to the index.

Using with django-cms apphooks

Add the Django Cms Faceted Search apphook to a page.

Indexes

django-cms-search provides a couple of useful helpers to deal with multilingual content.

class cms_facetsearch.indexes.TranslationIndex

A SearchIndex that adds a prepare_translated method and a faceted language field to the search index. An example for when this is useful is the app hook infrastructure from django CMS. When a model’s get_absolute_url() uses a url pattern that is attached to an app hook and there is a own model for titles per language the URL varies depending on the language or ay translated strings. A usage example:

# models.py

class Story(models.Model):
    pub_date = models.DateTimeField(default=datetime.datetime.now)

class StoryTitle(models.Model):
    story = models.ForeignKey(Story)
    language = models.CharField(max_length=15, choices=settings.LANGUAGES)
    title = models.CharField(max_length=255)
    slug = models.SlugField()

    def _get_absolute_url(self):
        return ('%sstory_detail' % self.language, (), {
            'year': self.story.pub_date.strftime('%Y'),
            'month': self.story.pub_date.strftime('%m'),
            'day': self.story.pub_date.strftime('%d'),
            'slug': self.slug
        })
    get_absolute_url = models.permalink(_get_absolute_url)

# search_indexes.py

from models import StoryTitle
from haystack import indexes, site
from cms_facetsearch.indexes import TranslationIndex

class StoryTitleIndex(TranslationIndex):
    text = indexes.CharField(document=True, use_template=True)
    title = indexes.CharField(model_attr='title')
    url = indexes.CharField(stored=True)

    def prepare_translated(self, obj, language):
        data = super(StoryTitleIndex, self).prepare_translated(self, obj, language)
        data['url'] = obj.get_absolute_url()
        return data

site.register(StoryTitle, StoryTitleIndex)

Note

  • In the above example, you might want to catch NoReverseMatch exceptions if you don’t have activated the app hook for all languages defined in LANGUAGES.

Note

django CMS monkeypatches django.core.urlresolvers.reverse() to enable language namespaces. To ensure that this monkeypatching happens before haystack autodiscovers your indexes, your search_sites.py should look somewhat like this, will be fixed to work properly in django-cms 2.2:

from cms.models import monkeypatch_reverse
import haystack

monkeypatch_reverse()
haystack.autodiscover()
class cms_facetsearch.indexes.PluginIndex

A cms_facetsearch:TranslationIndex subclass that renders plugins from for a specific language as a document CharField for all placeholdes related to the model. A usage example:

# models.py

from cms.models.fields import PlaceholderField
# or from djangocms_utils.fields import M2MPlaceholderField

class Story(models.Model):
    pub_date = models.DateTimeField(default=datetime.datetime.now)
    placeholder = PlaceholderField()

class StoryTitle(models.Model):
    story = models.ForeignKey(Story)
    language = models.CharField(max_length=15, choices=settings.LANGUAGES)
    title = models.CharField(max_length=255)
    slug = models.SlugField()

# search_indexes.py

from models import StoryTitle
from haystack import indexes, site
from cms_facetsearch.indexes import PluginIndex

class StoryTitleIndex(PluginIndex):
    title = indexes.CharField(model_attr='title')
    url = indexes.CharField(stored=True)

    def get_placeholders(self, obj, language):
        return [obj.story.placeholder]

site.register(StoryTitle, StoryTitleIndex)

Advanced

The current development version of django-cms-facetsearch supports haystack-celery so you can update the index when saving the model you want to index or a plugin related to the model you want to index.

All you need to do to activate this is to set up django-celery and add haystack_celery to INSTALLED_APPS.

Finding the model related to the plugins requires a extara hook ``get_index_instance_from_plugin``to query for the instance. The search_index for the Django CMS pages and cmsplugin-blog already has this method defined.

# models.py

from cms.models.fields import PlaceholderField
# or from djangocms_utils.fields import M2MPlaceholderField

class Story(models.Model):
    pub_date = models.DateTimeField(default=datetime.datetime.now)
    placeholder = PlaceholderField()

class StoryTitle(models.Model):
    story = models.ForeignKey(Story)
    language = models.CharField(max_length=15, choices=settings.LANGUAGES)
    title = models.CharField(max_length=255)
    slug = models.SlugField()

from models import StoryTitle
from haystack import indexes, site
from cms_facetsearch.indexes import PluginIndex

class StoryTitleIndex(PluginIndex):
    title = indexes.CharField(model_attr='title')
    url = indexes.CharField(stored=True)

    def get_placeholders(self, obj, language):
        return [obj.story.placeholder]

def get_index_instance_from_plugin(self, instance, **kwargs):
    try:
        return StoryTitle.objects.get(story__placeholder__cmsplugin=instance)
    except StoryTitle.DoesNotExist:
         return None

site.register(StoryTitle, StoryTitleIndex)

Settings

CMS_FACETSEARCH_REGISTER_SEARCHINDEX

Default: :boolean:`True`

This setting can be used to disable registering of django-cms Titles with a cms_facetsearch:PluginIndex if you use another search solution for cms core.

CMS_FACETSEARCH_LABEL_OVERRIDES

Default: :dict:`{}`

This setting can be used to change the labels for model selection in the search form Eg. CMS_FACETSEARCH_LABEL_OVERRIDES={‘news.storytitle’: gettext(‘Stories’) }

Project Versions

Table Of Contents

This Page