You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

facets.py 4.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. from django.conf import settings
  2. from purl import URL
  3. from haystack.query import SearchQuerySet
  4. def base_sqs():
  5. """
  6. Return the base SearchQuerySet for Haystack searches.
  7. """
  8. sqs = SearchQuerySet()
  9. for facet in settings.OSCAR_SEARCH_FACETS['fields'].values():
  10. options = facet.get('options', {})
  11. sqs = sqs.facet(facet['field'], **options)
  12. for facet in settings.OSCAR_SEARCH_FACETS['queries'].values():
  13. for query in facet['queries']:
  14. sqs = sqs.query_facet(facet['field'], query[1])
  15. return sqs
  16. class FacetMunger(object):
  17. def __init__(self, path, selected_multi_facets, facet_counts):
  18. self.base_url = URL(path)
  19. self.selected_facets = selected_multi_facets
  20. self.facet_counts = facet_counts
  21. def facet_data(self):
  22. facet_data = {}
  23. # Haystack can return an empty dict for facet_counts when e.g. Solr
  24. # isn't running. Skip facet munging in that case.
  25. if self.facet_counts:
  26. self.munge_field_facets(facet_data)
  27. self.munge_query_facets(facet_data)
  28. return facet_data
  29. def munge_field_facets(self, clean_data):
  30. for key, facet in settings.OSCAR_SEARCH_FACETS['fields'].items():
  31. self.munge_field_facet(key, facet, clean_data)
  32. def munge_field_facet(self, key, facet, clean_data):
  33. clean_data[key] = {
  34. 'name': facet['name'],
  35. 'results': []}
  36. for field_value, count in self.facet_counts['fields'][key]:
  37. field_name = '%s_exact' % facet['field']
  38. is_faceted_already = field_name in self.selected_facets
  39. datum = {
  40. 'name': field_value,
  41. 'count': count,
  42. # We don't show facet counts if a this field is already being
  43. # faceted (as we don't know them)
  44. 'show_count': not is_faceted_already,
  45. 'disabled': count == 0 and not is_faceted_already,
  46. 'selected': False
  47. }
  48. if field_value in self.selected_facets.get(field_name, []):
  49. # This filter is selected - build the 'deselect' URL
  50. datum['selected'] = True
  51. url = self.base_url.remove_query_param(
  52. 'selected_facets', '%s:%s' % (
  53. field_name, field_value))
  54. datum['deselect_url'] = self.strip_pagination(url)
  55. else:
  56. # This filter is not selected - built the 'select' URL
  57. url = self.base_url.append_query_param(
  58. 'selected_facets', '%s:%s' % (
  59. field_name, field_value))
  60. datum['select_url'] = self.strip_pagination(url)
  61. clean_data[key]['results'].append(datum)
  62. def munge_query_facets(self, clean_data):
  63. for key, facet in settings.OSCAR_SEARCH_FACETS['queries'].items():
  64. self.munge_query_facet(key, facet, clean_data)
  65. def munge_query_facet(self, key, facet, clean_data):
  66. clean_data[key] = {
  67. 'name': facet['name'],
  68. 'results': []}
  69. # Loop over the queries in OSCAR_SEARCH_FACETS rather than the returned
  70. # facet information from the search backend.
  71. for field_value, query in facet['queries']:
  72. field_name = '%s_exact' % facet['field']
  73. is_faceted_already = field_name in self.selected_facets
  74. match = '%s:%s' % (field_name, query)
  75. if match not in self.facet_counts['queries']:
  76. # This query was not returned
  77. datum = {
  78. 'name': field_value,
  79. 'count': 0,
  80. 'show_count': True,
  81. 'disabled': True,
  82. }
  83. else:
  84. count = self.facet_counts['queries'][match]
  85. datum = {
  86. 'name': field_value,
  87. 'count': count,
  88. 'show_count': not is_faceted_already,
  89. 'disabled': count == 0 and not is_faceted_already,
  90. 'selected': False,
  91. }
  92. if query in self.selected_facets.get(field_name, []):
  93. # Selected
  94. datum['selected'] = True
  95. datum['show_count'] = True
  96. url = self.base_url.remove_query_param(
  97. 'selected_facets', match)
  98. datum['deselect_url'] = self.strip_pagination(url)
  99. else:
  100. url = self.base_url.append_query_param(
  101. 'selected_facets', match)
  102. datum['select_url'] = self.strip_pagination(url)
  103. clean_data[key]['results'].append(datum)
  104. def strip_pagination(self, url):
  105. if url.has_query_param('page'):
  106. url = url.remove_query_param('page')
  107. return url.as_string()