Improve recipe search

* Use more traditional GET instead of POST method
* Search in pn, summary, description and filename instead of just pn

Signed-off-by: Paul Eggleton <paul.eggleton@linux.intel.com>
This commit is contained in:
Paul Eggleton 2013-02-19 15:54:43 +00:00
parent fd600fb716
commit 430ae4f90e
4 changed files with 50 additions and 13 deletions

3
README
View File

@ -91,5 +91,6 @@ Bundled jQuery is redistributed under the MIT license.
Bundled uitablefilter.js is redistributed under the MIT license.
All other content is copyright (C) 2013 Intel Corporation and licensed
under the MIT license - see COPYING.MIT for details.
under the MIT license (unless otherwise noted) - see COPYING.MIT for
details.

View File

@ -31,9 +31,8 @@
<div class="row-fluid">
<div class="input-append">
<form id="filter-form" action="{% url recipe_search %}" method="post">
{% csrf_token %}
<input type="text" class="input-xxlarge" id="appendedInputButtons" placeholder="Search recipes" name="filter" value="{{ search_keyword }}" />
<form id="filter-form" action="{% url recipe_search %}" method="get">
<input type="text" class="input-xxlarge" id="appendedInputButtons" placeholder="Search recipes" name="q" value="{{ search_keyword }}" />
<button class="btn" type="submit">search</button>
</form>
</div>

View File

@ -0,0 +1,39 @@
# Borrowed from http://julienphalip.com/post/2825034077/adding-search-to-a-django-site-in-a-snap
# Copyright 2011 Julien Phalip. All Rights Reserved.
import re
from django.db.models import Q
def normalize_query(query_string,
findterms=re.compile(r'"([^"]+)"|(\S+)').findall,
normspace=re.compile(r'\s{2,}').sub):
''' Splits the query string in invidual keywords, getting rid of unecessary spaces
and grouping quoted words together.
Example:
>>> normalize_query(' some random words "with quotes " and spaces')
['some', 'random', 'words', 'with quotes', 'and', 'spaces']
'''
return [normspace(' ', (t[0] or t[1]).strip()) for t in findterms(query_string)]
def get_query(query_string, search_fields):
''' Returns a query, that is a combination of Q objects. That combination
aims to search keywords within a model by testing the given search fields.
'''
query = None # Query to search for every search term
terms = normalize_query(query_string)
for term in terms:
or_query = None # Query to search for a given term in each field
for field_name in search_fields:
q = Q(**{"%s__icontains" % field_name: term})
if or_query is None:
or_query = q
else:
or_query = or_query | q
if query is None:
query = or_query
else:
query = query & or_query
return query

View File

@ -19,6 +19,7 @@ from django.db.models import Q
from django.core.mail import EmailMessage
from django.template.loader import get_template
from django.template import Context
import simplesearch
import settings
@ -96,22 +97,19 @@ class LayerListView(ListView):
class RecipeSearchView(ListView):
context_object_name = 'recipe_list'
paginate_by = 20
paginate_by = 10
def get_queryset(self):
keyword = self.request.session.get('keyword')
if keyword:
return Recipe.objects.all().filter(pn__icontains=keyword).order_by('pn', 'layer')
query_string = self.request.GET.get('q', '')
if query_string.strip():
entry_query = simplesearch.get_query(query_string, ['pn', 'summary', 'description', 'filename'])
return Recipe.objects.filter(entry_query).order_by('pn', 'layer')
else:
return Recipe.objects.all().order_by('pn', 'layer')
def post(self, request, *args, **kwargs):
request.session['keyword'] = request.POST['filter']
return HttpResponseRedirect(reverse('recipe_search'))
def get_context_data(self, **kwargs):
context = super(RecipeSearchView, self).get_context_data(**kwargs)
context['search_keyword'] = self.request.session.get('keyword') or ''
context['search_keyword'] = self.request.GET.get('q', '')
return context