Source code for oscar.apps.search.facets

from collections import OrderedDict

from django.conf import settings
from haystack.query import SearchQuerySet
from purl import URL


[docs]def base_sqs(): """ Return the base SearchQuerySet for Haystack searches. """ sqs = SearchQuerySet() for facet in settings.OSCAR_SEARCH_FACETS['fields'].values(): options = facet.get('options', {}) sqs = sqs.facet(facet['field'], **options) for facet in settings.OSCAR_SEARCH_FACETS['queries'].values(): for query in facet['queries']: sqs = sqs.query_facet(facet['field'], query[1]) return sqs
class FacetMunger(object): def __init__(self, path, selected_multi_facets, facet_counts): self.base_url = URL(path) self.selected_facets = selected_multi_facets self.facet_counts = facet_counts def facet_data(self): facet_data = OrderedDict() # Haystack can return an empty dict for facet_counts when e.g. Solr # isn't running. Skip facet munging in that case. if self.facet_counts: self.munge_field_facets(facet_data) self.munge_query_facets(facet_data) return facet_data def munge_field_facets(self, clean_data): for key, facet in settings.OSCAR_SEARCH_FACETS['fields'].items(): self.munge_field_facet(key, facet, clean_data) def munge_field_facet(self, key, facet, clean_data): clean_data[key] = { 'name': facet['name'], 'results': []} for field_value, count in self.facet_counts['fields'][key]: field_name = '%s_exact' % facet['field'] is_faceted_already = field_name in self.selected_facets datum = { 'name': field_value, 'count': count, # We don't show facet counts if a this field is already being # faceted (as we don't know them) 'show_count': not is_faceted_already, 'disabled': count == 0 and not is_faceted_already, 'selected': False } if field_value in self.selected_facets.get(field_name, []): # This filter is selected - build the 'deselect' URL datum['selected'] = True url = self.base_url.remove_query_param( 'selected_facets', '%s:%s' % ( field_name, field_value)) datum['deselect_url'] = self.strip_pagination(url) else: # This filter is not selected - built the 'select' URL url = self.base_url.append_query_param( 'selected_facets', '%s:%s' % ( field_name, field_value)) datum['select_url'] = self.strip_pagination(url) clean_data[key]['results'].append(datum) def munge_query_facets(self, clean_data): for key, facet in settings.OSCAR_SEARCH_FACETS['queries'].items(): self.munge_query_facet(key, facet, clean_data) def munge_query_facet(self, key, facet, clean_data): clean_data[key] = { 'name': facet['name'], 'results': []} # Loop over the queries in OSCAR_SEARCH_FACETS rather than the returned # facet information from the search backend. for field_value, query in facet['queries']: field_name = '%s_exact' % facet['field'] is_faceted_already = field_name in self.selected_facets match = '%s:%s' % (field_name, query) if match not in self.facet_counts['queries']: # This query was not returned datum = { 'name': field_value, 'count': 0, 'show_count': True, 'disabled': True, } else: count = self.facet_counts['queries'][match] datum = { 'name': field_value, 'count': count, 'show_count': not is_faceted_already, 'disabled': count == 0 and not is_faceted_already, 'selected': False, } if query in self.selected_facets.get(field_name, []): # Selected datum['selected'] = True datum['show_count'] = True url = self.base_url.remove_query_param( 'selected_facets', match) datum['deselect_url'] = self.strip_pagination(url) else: url = self.base_url.append_query_param( 'selected_facets', match) datum['select_url'] = self.strip_pagination(url) clean_data[key]['results'].append(datum) def strip_pagination(self, url): if url.has_query_param('page'): url = url.remove_query_param('page') return url.as_string()