Darwin Tech
Darwin Tech

Reputation: 18919

Django - storing queryset in request.session still queries the db - why?

def mysearch(request):
    """This view builds a Q object query based on which fields are filled."""
    if 'submit' in request.POST:
        # build Q object depending on fields submitted
        q = Q()
        if request.POST['first_field']:
            q &= Q(firstfield__icontains = request.POST['first_field'])

        ...

        if request.POST['sixth_field']:
            q &= Q(sixthfield__icontains = request.POST['sixth_field'])

        results_list = MyModel.objects.filter(q)
        count = len(results_list)

        # store results
        request.session['results_list'] = results_list
        request.session['count'] = count

    # 'p' is an arbitrary marker to detonate pagination of a page other than 1 
    if 'p' in request.GET:
        results_list = request.session['results_list']
        count = request.session['count']

    if count and count > 0:
        ...
        # pagination code
        ...

    else:
        pass
    return render_to_response('search_results.html',
        locals(), context_instance=RequestContext(request)) 

All works well in my templates using the paginator. The problem is that Django debug toolbar tells me that I am hitting the database the same number of times on pages > 1 than I am on the first page. Why is this? In fact - why is it hitting the database at all? Shouldn't the whole results_list be being pulled from request.session? Any advice much appreciated.

Upvotes: 3

Views: 2556

Answers (1)

Leopd
Leopd

Reputation: 42737

You're saving a queryset object in the session. Querysets are like SQL statements, but they cache the results. You haven't run the query when you put it in the session, so what you're storing is essentially just the query. When it gets pulled out it's still just a query that hasn't run, so the queryset gets run again. To ensure that you're storing just the actual results, do this:

request.session['results_list'] = list(results_list)

and to save you another query when you find count you can...

request.session['count'] = len(request.session['results_list'])

Also keep in mind that session data is (by default) saved in the database, so you might not be doing yourself any favors by storing a python pickled representation of the full data. It might in fact be faster just to go to the original table and pull it out that way.

Upvotes: 4

Related Questions