[Django]-Django pagination overhead with sorting

7👍

Django is very smart about lazy-loading the data, which makes these queries very efficient. Let’s walk through what happens with your requests…

eList = Employer.objects.filter(eminence__lt=4).order_by('-eminence')
## No database query.

paginator = Paginator(eList, 3)
## No database query.

employerList = paginator.page(2)
## SELECT COUNT(*) FROM `yourproject_employer`
## WHERE `yourproject_employer`.`eminence` < 4

 # Force iteration.  Same as looping over results:
foo = list(employerList.object_list)
## SELECT * FROM `yourproject_employer`
## WHERE `yourproject_employer`.`eminence` < 4
## ORDER BY `yourproject_employer`.`eminence` DESC
## LIMIT 3 OFFSET 3

As for your sorting question, I would say to simply modify the GET arguments as you suggested. Just be very careful passing this to the database. I would, for example, make a list of possible sorts and verify against that. This also means you don’t have to expose the inner-workings of your database.

VALID_SORTS = {
    "pk": "pk",
    "pkd": "-pk",
    "em": "eminence",
    "emd": "-eminence",
}
DEFAULT_SORT = 'pk'
def search(request):
    sort_key = request.GET.get('sort', DEFAULT_SORT) # Replace pk with your default.
    sort = VALID_SORTS.get(sort_key, DEFAULT_SORT)

    eList = Employer.objects.filter(eminence__lt=4).order_by(sort)

0👍

I would strongly suggest endless_pagination. It is an awsum app.
Check out the sample project in here : https://github.com/venkasub/endless_pagination_example

0👍

Actually Paginator depends on slicing of QuerySet. Slicing is dependent on particular database – if django db adaptor supports it (e.g. transfers slice limits to SQL query – to something like LIMIT x OFFSET y for mysql or something else for other db). If this is supported, then query fetches only rows for given page.
I believe that for MySQL this feature is disabled now (I was looking into Django 1.3), because of performance issue with OFFSET clause.

👤Ivan

Leave a comment