brydon wrote:
> I'm curious what people are currently using for search frameworks on
> django based projects. I've done a fair bit of research here and
> elsewhere and I still haven't landed on a clear decision. What are
> people successfully using with django to get robust search
> capabilities a la lucene etc? Are pylucene, xapian working?
>
>
I've written a fairly decent search function for my app just using Q
objects and the icontains test (I'm thinking of updating it to use the
new iregexp test, so as to search only whole words). I guess this
wouldn't be so good if you're building a big site, but it works pretty
well on mine. It takes a space separated string of keywords (which can
include quoted phrases), and returns the items where each of the
keywords is in at least one of the given fields.
The code I've written so far is pasted below. It isn't very tidy at the
moment, but does work, and people are welcome to copy and adapt it if
they like. I'm thinking at some point to generalise what I've written
into a custom filter class which takes a list of fields and a string as
an argument, and then post the code on the wiki, if people think that's
worth doing?
import re
from django import newforms as forms
from django.http import Http404, HttpResponseRedirect
from django.shortcuts import render_to_response
from library.horace.models import Item, ItemInstance, Tag
from django.db.models import Q
class SimpleSearchForm(forms.Form):
string = forms.CharField(label='Text to search for',max_length=100)
fields = forms.ChoiceField([(1,'Author, Title or
Description'),(2,'Title or Description'),(3,'Title'),(4,'Author')],
label='Where to search')
type = forms.ChoiceField([(1,'Any
item'),(2,'Books'),(3,'Magazines'),(4,'Films'),(5,'Music')], label='What
kind of item to search')
def simple_search(request):
"""Displays a simple search form and processes it.
Each word or phrase (marked by double quotes) has to be in at least
one of the fields indicated"""
if request.method == 'POST':
form = SimpleSearchForm(request.POST)
if form.is_valid():
item_list=Item.objects.all()
string=request.POST.get('string','')
fields=request.POST.get('fields',1)
type=request.POST.get('type',1)
# first split the input string into seperate words or phrases.
# I.e. the string '"mandrake linux" compiler c' becomes:
# ('mandrake linux','compiler','c')
# begin by taking out the double-quoted phrases.
reqt=re.compile(r'["\'](.*?)["\']')
phrases=reqt.findall(string)
#print "phrases: %s" % phrases
string=reqt.sub('',string) # remove the phrases
#print "string: %s" % string
rewd=re.compile(r'(\w+)( |$)')
resp=re.compile(r' ') # TODO - work out why there's an extra
space at the end of words in the first place.
for pair in rewd.finditer(string):
wd=resp.sub('',pair.group())
#print "wd: -%s-" % wd
phrases.append(wd)
#print "phrases: %s" % phrases
# now phrases contains a list of terms to search for.
# next thing is to find which items contain all of the terms
in at least one of the given fields.
# for each term, make a Q object which selects if it is in
at least one of the given fields...
qand=None # TODO -find out if there is a null Q object you
can start with without having to check if it's None later.
for phrase in phrases:
qor=None # a 'Q object' which can be combined with other
Q objects to represent a complex query. see django documentation.
if (fields=='1') or (fields=='2') or (fields=='3'):
qor=Q(title__icontains=phrase)
if fields=='1' or fields=='4':
if qor==None:
qor=Q(creator__icontains=phrase)
else:
qor=qor | Q(creator__icontains=phrase)
if fields=='1' or fields=='2':
qor=qor | Q(description__icontains=phrase)
# now qor must contain something, so 'and' it with the
rest if there are any yet
if qand != None:
qand=qand & qor
else:
qand=qor
if qand != None:
item_list=item_list.filter(qand)
# now process the 'type' field.
mapping={'2': 1, '3': 2, '4': 3, '5': 4}
if type in mapping.keys():
item_list=item_list.filter(item_type=mapping[type])
#print "item_list: %s" % item_list
#print "item_list._filters %s" % item_list._filters
length=item_list.count()
return render_to_response('simple-search.html',{'item_list':
item_list,
#'search_string': "containing '%s'" % string,
'length': length,
'show_results': True,
'form': form})
else:
form = SimpleSearchForm()
return render_to_response('simple-search.html', {'form': form})
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"Django users" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at
http://groups.google.com/group/django-users?hl=en
-~----------~----~----~----~------~----~------~--~---