forked from django-haystack/django-haystack
-
Notifications
You must be signed in to change notification settings - Fork 4
/
forms.py
126 lines (86 loc) · 4.05 KB
/
forms.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
from __future__ import unicode_literals
from django import forms
from django.db import models
from django.utils.text import capfirst
from django.utils.translation import ugettext_lazy as _
from haystack import connections
from haystack.constants import DEFAULT_ALIAS
from haystack.query import SearchQuerySet, EmptySearchQuerySet
try:
from django.utils.encoding import smart_text
except ImportError:
from django.utils.encoding import smart_unicode as smart_text
def model_choices(using=DEFAULT_ALIAS):
choices = [("%s.%s" % (m._meta.app_label, m._meta.module_name), capfirst(smart_text(m._meta.verbose_name_plural))) for m in connections[using].get_unified_index().get_indexed_models()]
return sorted(choices, key=lambda x: x[1])
class SearchForm(forms.Form):
q = forms.CharField(required=False, label=_('Search'))
def __init__(self, *args, **kwargs):
self.searchqueryset = kwargs.pop('searchqueryset', None)
self.load_all = kwargs.pop('load_all', False)
if self.searchqueryset is None:
self.searchqueryset = SearchQuerySet()
super(SearchForm, self).__init__(*args, **kwargs)
def no_query_found(self):
"""
Determines the behavior when no query was found.
By default, no results are returned (``EmptySearchQuerySet``).
Should you want to show all results, override this method in your
own ``SearchForm`` subclass and do ``return self.searchqueryset.all()``.
"""
return EmptySearchQuerySet()
def search(self):
if not self.is_valid():
return self.no_query_found()
if not self.cleaned_data.get('q'):
return self.no_query_found()
sqs = self.searchqueryset.auto_query(self.cleaned_data['q'])
if self.load_all:
sqs = sqs.load_all()
return sqs
def get_suggestion(self):
if not self.is_valid():
return None
return self.searchqueryset.spelling_suggestion(self.cleaned_data['q'])
class HighlightedSearchForm(SearchForm):
def search(self):
return super(HighlightedSearchForm, self).search().highlight()
class FacetedSearchForm(SearchForm):
def __init__(self, *args, **kwargs):
self.selected_facets = kwargs.pop("selected_facets", [])
super(FacetedSearchForm, self).__init__(*args, **kwargs)
def search(self):
sqs = super(FacetedSearchForm, self).search()
# We need to process each facet to ensure that the field name and the
# value are quoted correctly and separately:
for facet in self.selected_facets:
if ":" not in facet:
continue
field, value = facet.split(":", 1)
if value:
sqs = sqs.narrow(u'%s:"%s"' % (field, sqs.query.clean(value)))
return sqs
class ModelSearchForm(SearchForm):
def __init__(self, *args, **kwargs):
super(ModelSearchForm, self).__init__(*args, **kwargs)
self.fields['models'] = forms.MultipleChoiceField(choices=model_choices(), required=False, label=_('Search In'), widget=forms.CheckboxSelectMultiple)
def get_models(self):
"""Return an alphabetical list of model classes in the index."""
search_models = []
if self.is_valid():
for model in self.cleaned_data['models']:
search_models.append(models.get_model(*model.split('.')))
return search_models
def search(self):
sqs = super(ModelSearchForm, self).search()
return sqs.models(*self.get_models())
class HighlightedModelSearchForm(ModelSearchForm):
def search(self):
return super(HighlightedModelSearchForm, self).search().highlight()
class FacetedModelSearchForm(ModelSearchForm):
selected_facets = forms.CharField(required=False, widget=forms.HiddenInput)
def search(self):
sqs = super(FacetedModelSearchForm, self).search()
if hasattr(self, 'cleaned_data') and self.cleaned_data['selected_facets']:
sqs = sqs.narrow(self.cleaned_data['selected_facets'])
return sqs.models(*self.get_models())