Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. import json
  2. from django.http import HttpResponse, HttpResponseRedirect
  3. from django.views.generic.base import View
  4. from django.conf import settings
  5. from django.db.models import get_model
  6. from haystack.query import SearchQuerySet
  7. from haystack import views
  8. from purl import URL
  9. Product = get_model('catalogue', 'Product')
  10. class SuggestionsView(View):
  11. """
  12. Auto suggest view
  13. Returns the suggestions in JSON format (especially suited for consumption
  14. by jQuery autocomplete) """
  15. suggest_limit = settings.OSCAR_SEARCH_SUGGEST_LIMIT
  16. def get(self, request):
  17. context = self.get_context_data()
  18. return self.render_to_response(context)
  19. def get_context_data(self):
  20. '''
  21. Creates a list of suggestions
  22. '''
  23. query_term = self.request.GET['query_term']
  24. query_set = SearchQuerySet().filter(text__contains=query_term)[
  25. :self.suggest_limit]
  26. context = []
  27. for item in query_set:
  28. context.append({
  29. 'label': item.object.title,
  30. 'url': item.object.get_absolute_url(),
  31. })
  32. return context
  33. def render_to_response(self, context):
  34. "Returns a JSON response containing 'context' as payload"
  35. return self.get_json_response(self.convert_context_to_json(context))
  36. def get_json_response(self, content, **httpresponse_kwargs):
  37. "Construct an `HttpResponse` object."
  38. return HttpResponse(content,
  39. content_type='application/json',
  40. **httpresponse_kwargs)
  41. def convert_context_to_json(self, context):
  42. "Convert the context into a JSON object"
  43. return json.dumps(context)
  44. class FacetedSearchView(views.FacetedSearchView):
  45. def extra_context(self):
  46. extra = super(FacetedSearchView, self).extra_context()
  47. if 'fields' not in extra['facets']:
  48. # Looks like Solr is not responding correctly
  49. return extra
  50. # Convert facet data into a more useful datastructure
  51. # Field facets
  52. facet_data = {}
  53. base_url = URL(self.request.get_full_path())
  54. selected = dict(
  55. map(lambda x: x.split(':'), self.form.selected_facets))
  56. for field, facets in extra['facets']['fields'].items():
  57. facet_data[field] = []
  58. for name, count in facets:
  59. # Ignore zero-count facets for field
  60. if count == 0:
  61. continue
  62. field_filter = '%s_exact' % field
  63. datum = {
  64. 'name': name,
  65. 'count': count}
  66. if selected.get(field_filter, None) == name:
  67. # This filter is selected - build the 'deselect' URL
  68. datum['selected'] = True
  69. url = base_url.remove_query_param(
  70. 'selected_facets', '%s:%s' % (
  71. field_filter, name))
  72. datum['deselect_url'] = url.as_string()
  73. else:
  74. # This filter is not selected - built the 'select' URL
  75. datum['selected'] = False
  76. url = base_url.append_query_param(
  77. 'selected_facets', '%s:%s' % (
  78. field_filter, name))
  79. datum['select_url'] = url.as_string()
  80. facet_data[field].append(datum)
  81. # Query facets
  82. for key, facet in settings.OSCAR_SEARCH_FACETS['queries'].items():
  83. facet_data[key] = []
  84. for name, query in facet['queries']:
  85. field_filter = '%s_exact' % facet['field']
  86. match = '%s_exact:%s' % (facet['field'], query)
  87. if not match in extra['facets']['queries']:
  88. datum = {
  89. 'name': name,
  90. 'count': 0,
  91. }
  92. else:
  93. datum = {
  94. 'name': name,
  95. 'count': extra['facets']['queries'][match],
  96. }
  97. if selected.get(field_filter, None) == query:
  98. # Selected
  99. datum['selected'] = True
  100. url = base_url.remove_query_param(
  101. 'selected_facets', match)
  102. datum['deselect_url'] = url.as_string()
  103. else:
  104. datum['selected'] = False
  105. url = base_url.append_query_param(
  106. 'selected_facets', match)
  107. datum['select_url'] = url.as_string()
  108. facet_data[key].append(datum)
  109. extra['facet_data'] = facet_data
  110. return extra
  111. class MultiFacetedSearchView(FacetedSearchView):
  112. """
  113. Search view for multifaceted searches
  114. """
  115. template = 'search/results.html'
  116. def __call__(self, request, *args, **kwargs):
  117. """
  118. Generates the actual response to the search.
  119. Relies on internal, overridable methods to construct the response.
  120. """
  121. # Look for UPC match
  122. query = request.GET.get('q', '').strip()
  123. try:
  124. item = Product._default_manager.get(upc=query)
  125. return HttpResponseRedirect(item.get_absolute_url())
  126. except Product.DoesNotExist:
  127. pass
  128. return super(MultiFacetedSearchView, self).__call__(request, *args, **kwargs)
  129. @property
  130. def __name__(self):
  131. return "MultiFacetedSearchView"
  132. def extra_context(self):
  133. """
  134. Adds details about the facets applied
  135. """
  136. extra = super(MultiFacetedSearchView, self).extra_context()
  137. if hasattr(self.form, 'cleaned_data') and 'selected_facets' in self.form.cleaned_data:
  138. extra['facets_applied'] = []
  139. for f in self.form.cleaned_data['selected_facets'].split("|"):
  140. facet = f.split(":")
  141. extra['facets_applied'].append({
  142. 'facet': facet[0][:-6], # removing the _exact suffix that haystack uses for some reason
  143. 'value' : facet[1].strip('"')
  144. })
  145. return extra