Search results pagination

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
search_cache = get_cache('locmem:///')
_CACHE_TIMEOUT = 60*60*5 # 5 min

def search_cacheable(lang, query):
    key = urllib.quote(lang + query)
    if not search_cache.get(key):
        results4blogs = Entry.objects.all()
        results4pages = Page.objects.filter(language__exact=lang)
        results4photos = Photo.objects.all()
        results4comments = Comment.objects.all()
        for term in query.split():
            results4blogs = results4blogs.filter(Q(headline__icontains=term) | Q(body__icontains=term))
            results4pages = results4pages.filter(Q(title__icontains=term) | Q(content__icontains=term))
            results4photos = results4photos.filter(Q(title__icontains=term))
            results4comments = results4comments.filter(Q(headline__icontains=term) | Q(comment__icontains=term))

        rslt = list(set(results4blogs) | set(results4pages) | set(results4photos) | set(results4comments))
        search_cache.set(key, rslt, _CACHE_TIMEOUT)
        print 'cache created for "%s" in %s' % (query, lang.upper())
    else:
        rslt = search_cache.get(key)
        print 'cache hit for "%s" in %s' % (query, lang.upper())
    return rslt

def paginate_results(request):
    paginate_by = 5
    orphans = 1

    lang = request.LANGUAGE_CODE
    page = int(request.GET.get('page', '1'))
    query = urllib.unquote(request.GET.get('search_query', '')).lower()
    
    results = search_cacheable(lang, query)
    paginator = ObjectPaginator(results, paginate_by, orphans)
    
    try:
        collection = paginator.get_page(page - 1)
    except InvalidPage:
        raise Http404
    
    return render_to_response('results.html', 
                              {'results': collection,
                               'query':query,
                               'is_paginated': paginator.pages > 1,
                               'results_per_page': paginate_by,
                               'has_next': paginator.has_next_page(page - 1),
                               'has_previous': paginator.has_previous_page(page - 1),
                               'page': page,
                               'next': page + 1,
                               'previous': page - 1,
                               'pages': paginator.pages,
                               'hits' : paginator.hits,}, 
                               context_instance=RequestContext(request),)

More like this

  1. Tags & filters for rendering search results by exogen 6 years, 1 month ago
  2. better paginator template tag by amitu 5 years, 6 months ago
  3. Dynamic query builder with AND/OR by bobwaycott 4 years, 8 months ago
  4. Pagination/Filtering Alphabetically by zain 5 years, 1 month ago
  5. Paginator TemplateTag by trbs 6 years ago

Comments

polarbear (on March 31, 2007):

I made mistake:

You search by firing GET

should say:

You search by firing POST

#

svetlyak (on April 1, 2007):

Cool! But how about parallel searches by different users? Seems I get wrong results if someone run search query before I click on Next Page Link :)

#

polarbear (on April 1, 2007):

You are right. Must be something to do with cache control, vary on headers or similar. If you find solution, please post it.

#

esaj (on April 13, 2007):

This is a bad idea if the search returns a large number of hits, as it will load them all into memory.

#

(Forgotten your password?)