This is fairly well documented in the Django docs, so I'll be brief. This is the the bit of search code I use in almost all of my Django sites, and it works great:
def search(request): from django.db.models import Q q = request.GET.get("q", "") if q and len(q) >= 3: clause = Q(dirtword__icontains=q) \ | Q(description__icontains=q) \ | Q(tags__name__icontains=q) site_search = Dirt.objects.filter(clause).distinct() else: site_search = Dirt.objects.order_by('?')[:100] return list_detail.object_list( request = request, queryset = site_search, template_name = "dirty/search.html", template_object_name = "dirty", paginate_by = 20, extra_context = {"q" : q}, )
While this should be pretty self-explanatory, the process goes like this: q is taken from the GET request and if it is over three characters long, it is searched for in the dirtword column, through the description and also through the m2m relationship of tags__name. Yup, it is pretty nifty to be able to access relationship in this way (tags__name). You will notice that at the end of each search it says "__icontains" -- this simply does a fuzzy search for the word. Once the queryset is created (the filter) I've added a .distinct() on the end --this prevents multiple rows from being returned to the template. If there isn't a search, or it isn't long enough, a random list will be returned.
One thing I like to do is include the search as extra_context -- this allows you to say something like "you've searched for..." at the top of your search. I couldn't imagine implementing a search feature as being any easier.
Thanks for the tips, Tom! I'll look into altering my searching mechanism to utilize full-text search, and will update the end of this post when I do. Ahh, the things you learn when people can peruse your code.
Unrelated, your posts crack me up sometimes (http://www.theotherblog.com/).
And now I have a Vietnam flag!
This entry is from my tech blog and was written on June 3, 2007. It's been tagged with django and search. There have been 3 comments so far.
Finally done sorting all my email. (about 1 week ago)
You really don't want to do that... trust me...
If you have lots of records (and one day you will) it will grind MySQL to a halt...
Firstly, icontains is a LIKE query. They are very slow. I think it may even have to create 3 queries to search properly, one for begins_with, one for endwith and one for contains.... ugh!. Instead create a fulltext index and use something like this...
products = Product.objects.all()
word_str = ''
for word in words:
word_str +="+" + word + " "
products = products.filter(name__search=word_str)
return products[:100]
Secondly, if you have multiple words, what happens?
Lastly, Ordering by "?" is a sure fire way to slow MySQL to nothing ...
Give it a whirl, you can add extra indexes and queries ... I just thought I'd let you know because fulltext searches are much faster than LIKEs.
cheers