changeset 415:d4d167876c25

Fixing #205; search result pagination wasn't including models. Created a custom model search form so that the query term and model selections would persist across pages.
author Brian Neal <bgneal@gmail.com>
date Sun, 10 Apr 2011 00:32:14 +0000
parents b1f939b1fb01
children aabee29cadac
files gpp/custom_search.py gpp/templates/search/search.html gpp/urls.py static/css/base.css
diffstat 4 files changed, 83 insertions(+), 36 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gpp/custom_search.py	Sun Apr 10 00:32:14 2011 +0000
@@ -0,0 +1,65 @@
+"""
+This module contains custom code to tailor the Haystack search application to
+our needs.
+
+"""
+import urllib
+
+from django import forms
+from haystack.views import SearchView
+from haystack.forms import ModelSearchForm
+
+
+MODEL_CHOICES = (
+    ('forums.topic', 'Forum Topics'),
+    ('forums.post', 'Forum Posts'),
+    ('news.story', 'News Stories'),
+    ('bio.userprofile', 'User Profiles'),
+    ('weblinks.link', 'Links'),
+    ('downloads.download', 'Downloads'),
+    ('podcast.item', 'Podcasts'),
+    ('ygroup.post', 'Yahoo Group Archives'),
+)
+
+
+class CustomModelSearchForm(ModelSearchForm):
+    """
+    This customized ModelSearchForm allows us to explictly label and order
+    the model choices.
+
+    """
+    q = forms.CharField(required=False, label='',
+            widget=forms.TextInput(attrs={'class': 'text', '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)
+
+
+class ModelSearchView(SearchView):
+    """
+    This custom search view puts an extra value in the template context named
+    search_parms. search_parms will contain the search term q plus any models
+    arguments all as a urlencoded string. This is useful for generating
+    pagination links in the template.
+
+    """
+    def search_params(self):
+        """
+        Return the q and models search parameters as a urlencoded string if the
+        form is valid. An empty string is returned if the form is not valid.
+
+        """
+        if self.form.is_valid():
+            q = self.form.cleaned_data['q']
+            models = self.form.cleaned_data['models']
+
+            params = [('q', q)]
+            params.extend([('models', model) for model in models])
+            return urllib.urlencode(params)
+
+        return ''
+
+    def extra_context(self):
+        return {'search_params': self.search_params() }
--- a/gpp/templates/search/search.html	Sat Apr 09 19:20:12 2011 +0000
+++ b/gpp/templates/search/search.html	Sun Apr 10 00:32:14 2011 +0000
@@ -5,7 +5,7 @@
 <script type="text/javascript">
 //<![CDATA[
 $(document).ready(function() {
-      chkboxes = $('#search-form input[type="checkbox"]');
+      var chkboxes = $('#search-form input[type="checkbox"]');
       $('#chk_all').click(function() {
          chkboxes.each(function(index) {
             $(this).attr('checked', true);
@@ -18,6 +18,7 @@
          });
          return false;
       });
+      $('#search-form ul').addClass('no-bullet-inline-block');
 });
 //]]>
 </script>
@@ -25,39 +26,10 @@
 {% block content %}
 <h2>Search <img src="{{ STATIC_URL }}icons/magnifier.png" alt="Search" /></h2>
 <form id="search-form" method="get" action=".">
-<table>
-   <tr>
-      <td><input type="text" name="q" id="id_q" size="48" class="text" /></td>
-      <td><input type="submit" value="Search" /></td>
-   </tr>
-</table>
+{{ form.q }} <input type="submit" value="Search" />
 <fieldset>
 <legend>Search in:</legend>
-<table>
-   <tr>
-      <td><input id="chk-forums-topics" type="checkbox" name="models" value="forums.topic" checked="checked" />
-         <label for="chk-forums-topics" class="pointer">Forum Topics</label></td>
-
-      <td><input id="chk-forums-post" type="checkbox" name="models" value="forums.post" checked="checked" />
-         <label for="chk-forums-post" class="pointer">Forum Posts</label></td>
-      <td><input id="chk-news" type="checkbox" name="models" value="news.story" checked="checked" />
-         <label for="chk-news" class="pointer">News Stories</label></td>
-   </tr>
-   <tr>
-      <td><input id="chk-profiles" type="checkbox" name="models" value="bio.userprofile" checked="checked" />
-         <label for="chk-profiles" class="pointer">User Profiles</label></td>
-      <td><input id="chk-links" type="checkbox" name="models" value="weblinks.link" checked="checked" />
-         <label for="chk-links" class="pointer">Links</label></td>
-      <td><input id="chk-dls" type="checkbox" name="models" value="downloads.download" checked="checked" />
-         <label for="chk-dls" class="pointer">Downloads</label></td>
-   </tr>
-   <tr>
-      <td><input id="chk-podcasts" type="checkbox" name="models" value="podcast.item" checked="checked" />
-         <label for="chk-podcasts" class="pointer">Podcasts</label></td>
-      <td colspan="2"><input id="chk-ygroup" type="checkbox" name="models" value="ygroup.post" checked="checked" />
-         <label for="chk-ygroup" class="pointer">Yahoo Group Archives</label></td>
-   </tr>
-</table>
+{{ form.models }}
 <p><a href="#" id="chk_all">Check all</a> | <a href="#" id="chk_none">Check none</a></p>
 </fieldset>
 </form>
@@ -88,9 +60,9 @@
 
       {% if page.has_previous or page.has_next %}
           <div>
-              {% if page.has_previous %}<a href="?q={{ query }}&amp;page={{ page.previous_page_number }}">{% endif %}&laquo; Previous{% if page.has_previous %}</a>{% endif %}
+              {% if page.has_previous %}<a href="?{{ search_params }}&amp;page={{ page.previous_page_number }}">{% endif %}&laquo; Previous{% if page.has_previous %}</a>{% endif %}
               |
-              {% if page.has_next %}<a href="?q={{ query }}&amp;page={{ page.next_page_number }}">{% endif %}Next &raquo;{% if page.has_next %}</a>{% endif %}
+              {% if page.has_next %}<a href="?{{ search_params }}&amp;page={{ page.next_page_number }}">{% endif %}Next &raquo;{% if page.has_next %}</a>{% endif %}
           </div>
       {% endif %}
   {% else %}
--- a/gpp/urls.py	Sat Apr 09 19:20:12 2011 +0000
+++ b/gpp/urls.py	Sun Apr 10 00:32:14 2011 +0000
@@ -3,10 +3,11 @@
 from django.contrib import admin
 from django.views.decorators.cache import cache_page
 
-from haystack.views import SearchView, search_view_factory
+from haystack.views import search_view_factory
 
 from news.feeds import LatestNewsFeed
 from forums.feeds import ForumsFeed
+from custom_search import ModelSearchView, CustomModelSearchForm
 
 
 admin.autodiscover()
@@ -51,7 +52,9 @@
 
 # Haystack search views
 urlpatterns += patterns('haystack.views',
-    url(r'^search/$', search_view_factory(view_class=SearchView, load_all=True),
+    url(r'^search/$',
+        search_view_factory(view_class=ModelSearchView,
+            form_class=CustomModelSearchForm, load_all=True),
         name='haystack_search'),
 )
 
--- a/static/css/base.css	Sat Apr 09 19:20:12 2011 +0000
+++ b/static/css/base.css	Sun Apr 10 00:32:14 2011 +0000
@@ -433,3 +433,10 @@
 div.news-story-container {
    padding: 0.5em;
 }
+
+ul.no-bullet-inline-block {
+ list-style: none;
+}
+ul.no-bullet-inline-block li {
+ display: inline-block;
+}