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.

forms.py 3.2KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. from django import forms
  2. from django.forms.widgets import Input
  3. from django.conf import settings
  4. from django.utils.translation import ugettext_lazy as _
  5. from haystack.forms import FacetedSearchForm
  6. class SearchInput(Input):
  7. """
  8. Defining a search type widget
  9. This is an HTML5 thing and works nicely with Safari, other browsers default
  10. back to using the default "text" type
  11. """
  12. input_type = 'search'
  13. class SearchForm(FacetedSearchForm):
  14. """
  15. In Haystack, the search form is used for interpretting
  16. and sub-filtering the SQS.
  17. """
  18. # Use a tabindex of 1 so that users can hit tab on any page and it will
  19. # focus on the search widget.
  20. q = forms.CharField(
  21. required=False, label=_('Search'),
  22. widget=SearchInput({"placeholder": _('Search'), "tabindex": "1"}))
  23. # Search
  24. RELEVANCY = "relevancy"
  25. NEWEST = "newest"
  26. PRICE_HIGH_TO_LOW = "price-desc"
  27. PRICE_LOW_TO_HIGH = "price-asc"
  28. TITLE_A_TO_Z = "title-asc"
  29. TITLE_Z_TO_A = "title-desc"
  30. SORT_BY_CHOICES = [
  31. (RELEVANCY, _("Relevancy")),
  32. (NEWEST, _("Newest")),
  33. (PRICE_HIGH_TO_LOW, _("Price high To low")),
  34. (PRICE_LOW_TO_HIGH, _("Price low To high")),
  35. (TITLE_A_TO_Z, _("Title A to Z")),
  36. (TITLE_Z_TO_A, _("Title Z to A")),
  37. ]
  38. # Map query params to sorting fields. Note relevancy isn't included here
  39. # as we assume results are returned in relevancy order in the absence of an
  40. # explicit sort field being passed to the search backend.
  41. SORT_BY_MAP = {
  42. NEWEST: '-date_created',
  43. PRICE_HIGH_TO_LOW: '-price',
  44. PRICE_LOW_TO_HIGH: 'price',
  45. TITLE_A_TO_Z: 'title_s',
  46. TITLE_Z_TO_A: '-title_s',
  47. }
  48. # Non Solr backends don't support dynamic fields so we just sort on title
  49. if 'solr' not in settings.HAYSTACK_CONNECTIONS['default']['ENGINE']:
  50. SORT_BY_MAP[TITLE_A_TO_Z] = 'title'
  51. SORT_BY_MAP[TITLE_Z_TO_A] = '-title'
  52. sort_by = forms.ChoiceField(
  53. choices=SORT_BY_CHOICES, widget=forms.Select(), required=False)
  54. def search(self):
  55. # We replace the 'search' method from FacetedSearchForm, so that we can
  56. # handle range queries
  57. # Note, we call super on a parent class as the default faceted view
  58. # escapes everything (which doesn't work for price range queries)
  59. sqs = super(FacetedSearchForm, self).search()
  60. # We need to process each facet to ensure that the field name and the
  61. # value are quoted correctly and separately:
  62. for facet in self.selected_facets:
  63. if ":" not in facet:
  64. continue
  65. field, value = facet.split(":", 1)
  66. if value:
  67. if field == 'price_exact':
  68. # Don't wrap value in speech marks and don't clean value
  69. sqs = sqs.narrow(u'%s:%s' % (field, value))
  70. else:
  71. sqs = sqs.narrow(u'%s:"%s"' % (
  72. field, sqs.query.clean(value)))
  73. if self.is_valid() and 'sort_by' in self.cleaned_data:
  74. sort_field = self.SORT_BY_MAP.get(
  75. self.cleaned_data['sort_by'], None)
  76. if sort_field:
  77. sqs = sqs.order_by(sort_field)
  78. return sqs