diff custom_search/forms.py @ 753:ad53d929281a

For issue #62, upgrade Haystack from 1.2.7 to 2.1.0.
author Brian Neal <bgneal@gmail.com>
date Fri, 03 Jan 2014 19:01:18 -0600
parents 99d7bf8cd712
children 20a3bf7a6370
line wrap: on
line diff
--- a/custom_search/forms.py	Wed Jan 01 19:52:07 2014 -0600
+++ b/custom_search/forms.py	Fri Jan 03 19:01:18 2014 -0600
@@ -3,7 +3,10 @@
 our needs.
 
 """
+import logging
+
 from django import forms
+from django.conf import settings
 from haystack.forms import ModelSearchForm
 
 
@@ -18,20 +21,79 @@
     ('ygroup.post', 'Yahoo Group Archives'),
 )
 
+logger = logging.getLogger(__name__)
+
 
 class CustomModelSearchForm(ModelSearchForm):
     """
     This customized ModelSearchForm allows us to explictly label and order
     the model choices.
 
+    We also provide "all words", "exact phrase", and "exclude" text input boxes.
+    Haystack 2.1.0's auto_query() function did not seem to work right so we just
+    rolled our own.
+
     """
-    q = forms.CharField(required=False, label='',
-            widget=forms.TextInput(attrs={'type': 'search',
-                                          'class': 'search',
-                                          'size': 48,
-                                          }))
+    q = forms.CharField(required=False, label='All these words',
+            widget=forms.TextInput(attrs={'type': 'search', 'class': 'search',
+                'size': 48}))
+    exact = forms.CharField(required=False, label='This exact word or phrase',
+            widget=forms.TextInput(attrs={'type': 'search', 'class': 'search',
+                'size': 48}))
+    exclude = forms.CharField(required=False, label='None of these words',
+            widget=forms.TextInput(attrs={'type': 'search', 'class': 'search',
+                'size': 48}))
 
     def __init__(self, *args, **kwargs):
         super(CustomModelSearchForm, self).__init__(*args, **kwargs)
         self.fields['models'] = forms.MultipleChoiceField(choices=MODEL_CHOICES,
-                label='', widget=forms.CheckboxSelectMultiple)
+                label='Search in', widget=forms.CheckboxSelectMultiple)
+
+    def clean(self):
+        if not settings.SEARCH_QUEUE_ENABLED:
+            raise forms.ValidationError("Our search function is offline for "
+                    "maintenance. Please try again later. "
+                    "We apologize for any inconvenience.")
+
+        if not (self.cleaned_data['q'] or self.cleaned_data['exact'] or
+                self.cleaned_data['exclude']):
+            raise forms.ValidationError('Please supply some search terms')
+
+        return self.cleaned_data
+
+    def search(self):
+        if not self.is_valid():
+            return self.no_query_found()
+
+        logger.info('Search executed: /%s/%s/%s/ in %s',
+            self.cleaned_data['q'],
+            self.cleaned_data['exact'],
+            self.cleaned_data['exclude'],
+            self.cleaned_data['models'])
+
+        sqs = self.searchqueryset
+
+        # Note that in Haystack 2.x content is untrusted and is automatically
+        # auto-escaped for us.
+        #
+        # Filter on the q terms; these should be and'ed together:
+        terms = self.cleaned_data['q'].split()
+        for term in terms:
+            sqs = sqs.filter(content=term)
+
+        # Exact words or phrases:
+        if self.cleaned_data['exact']:
+            sqs = sqs.filter(content__exact=self.cleaned_data['exact'])
+
+        # Exclude terms:
+        terms = self.cleaned_data['exclude'].split()
+        for term in terms:
+            sqs = sqs.exclude(content=term)
+
+        if self.load_all:
+            sqs = sqs.load_all()
+
+        # Apply model filtering
+        sqs = sqs.models(*self.get_models())
+
+        return sqs