Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django lazy QuerySet and pagination

Tags:

I read here that Django querysets are lazy, it won't be evaluated until it is actually printed. I have made a simple pagination using the django's built-in pagination. I didn't realize there were apps already such as "django-pagination", and "django-endless" which does that job for.

Anyway I wonder whether the QuerySet is still lazy when I for example do this

entries = Entry.objects.filter(...) paginator = Paginator(entries, 10) output = paginator.page(page) return HttpResponse(output) 

And this part is called every time I want to get whatever page I currently I want to view.

I need to know since I don't want unnecessary load to the database.

like image 650
starcorn Avatar asked May 11 '12 09:05

starcorn


People also ask

Why pagination is not working in Django?

Your contexts aren't right and your templates call to the pagination follow the same way, so when you call the pagination object it will will not return a result as you did not use it in your queryset for loop.

How to add pagination in Django project?

In the index function we have constructed a paginator object called p . This paginator creates page objects. Each Page object will have equal number of post objects. Then we retrieved the desired page number from the query parameter 'page' from a GET request.


2 Answers

If you want to see where are occurring, import django.db.connection and inspect queries

>>> from django.db import connection >>> from django.core.paginator import Paginator >>> queryset = Entry.objects.all() 

Lets create the paginator, and see if any queries occur:

>>> paginator = Paginator(queryset, 10) >>> print connection.queries  [] 

None yet.

>>> page = paginator.page(4) >>> page <Page 4 of 788> >>> print connection.queries  [{'time': '0.014', 'sql': 'SELECT COUNT(*) FROM `entry`'}] 

Creating the page has produced one query, to count how many entries are in the queryset. The entries have not been fetched yet.

Assign the page's objects to the variable 'objects':

>>> objects = page.object_list >>> print connection.queries [{'time': '0.014', 'sql': 'SELECT COUNT(*) FROM `entry`'}] 

This still hasn't caused the entries to be fetched.

Generate the HttpResponse from the object list

>>> response = HttpResponse(page.object_list) >>> print connection.queries [{'time': '0.014', 'sql': 'SELECT COUNT(*) FROM `entry`'}, {'time': '0.011', 'sql': 'SELECT `entry`.`id`, <snip> FROM `entry` LIMIT 10 OFFSET 30'}] 

Finally, the entries have been fetched.

like image 82
Alasdair Avatar answered Oct 03 '22 00:10

Alasdair


It is. Django's pagination uses the same rules/optimizations that apply to querysets.

This means it will start evaluating on return HttpResponse(output)

like image 44
rantanplan Avatar answered Oct 03 '22 01:10

rantanplan