Login

Search results pagination

Author:
polarbear
Posted:
March 31, 2007
Language:
Python
Version:
.96
Score:
3 (after 3 ratings)

Problem:

You search by firing POST and paginate by firing GET, so search results disappear on GET. I want to preserve searching results, so user can paginate them.

First I try to use some static class to keep search results, but this solution has bug (thanks to svetlyak). In multiuser environment other user searching got results from previous one. No @cache_control(private=True) helps so I decided to change searching schema by using GET in the first place and to supply query string on each 'paging' request. Also added some memory cache that expires after 5 min

In template

Please append query to each paging link:

<a href="?page={{ page_number }}
&amp;search_query={{ query|urlencode }}">
{{ page_number }}</a>

This snippet should keep search results on pagination in multiuser environment.

 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. Template tag - list punctuation for a list of items by shapiromatron 10 months, 2 weeks ago
  2. JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 10 months, 3 weeks ago
  3. Serializer factory with Django Rest Framework by julio 1 year, 5 months ago
  4. Image compression before saving the new model / work with JPG, PNG by Schleidens 1 year, 6 months ago
  5. Help text hyperlinks by sa2812 1 year, 7 months 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.

#

Please login first before commenting.