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 = {}
# 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()