11

I need to make real pagination instead of paginating on all retreived data. The example in Django documentation site, is like;

def listing(request):
    contact_list = Contacts.objects.all()
    paginator = Paginator(contact_list, 25) # Show 25 contacts per page

    page = request.GET.get('page')
    try:
        contacts = paginator.page(page)
    except PageNotAnInteger:
        # If page is not an integer, deliver first page.
        contacts = paginator.page(1)
    except EmptyPage:
        # If page is out of range (e.g. 9999), deliver last page of results.
        contacts = paginator.page(paginator.num_pages)

    return render_to_response('list.html', {"contacts": contacts})

This code is paginating records on all retreived records. But there is a trouble. Trying to retreive all record takes many time if there are so many records. I need a solution to retrieve the records page by page from database.

Is there another solution to do this in Django?

msanders
  • 5,739
  • 1
  • 29
  • 30
Ahmet DAL
  • 4,445
  • 9
  • 47
  • 71
  • 1
    This question has been answered before, see here: http://stackoverflow.com/questions/10548744/django-lazy-queryset-and-pagination – Christian Thieme Sep 05 '12 at 06:57

4 Answers4

22

You make a false assumption. Django does not retrieve all objects when paginating: it slices the queryset appropriately, which uses LIMIT and COUNT on the SQL.

Daniel Roseman
  • 588,541
  • 66
  • 880
  • 895
  • Do you mean; Contacts.objects.all() line in the code is given in question, does not retrieve all record? – Ahmet DAL Sep 05 '12 at 07:15
  • 6
    Correct. Query sets are lazy, as the docs explain, and no db call is made until they are iterated or sliced. – Daniel Roseman Sep 05 '12 at 07:25
  • Actually I should have mention that I'm using MongoDB and Mongo fork for DJango modelling. Probably this is for SQL databases, not Mongo fork. Because I tried it, It still retreives all data from db. It is probably lack of Mongo fork for DJango. But thank you I didn't know that. – Ahmet DAL Sep 07 '12 at 06:23
1

A QuerySet is a lazy object. When you assign contact_list = Contacts.objects.all(), Django will NOT hit the database. Until you call the methods such as count(), filter(), first(),..., or contact_list[1:5], Django will really retrieve data from the database. SQL statements that Django generate will correlate to each method and these SQL statments will be sent to the DB.

E.g: contact_list[1:5] generate a SQL statement have LIMIT and OFFSET clauses.

In Paginator class, the QuerySet will passed to the its constructor

paginator = Paginator(contact_list, 25)

When you call paginator.page(page), the statement is called:

return self._get_page(self.object_list[bottom:top], number, self)
Hùng Ng Vi
  • 1,251
  • 2
  • 14
  • 20
0

Look inside Paginator class (django/core/paginator.py), it fetches only required pages. There is only one problem on big tables: if you want to show total page numbers you must make count(*) on entire table which can took a long time in some databases (i.e. postgresql, mysql with innodb).

BTW, try to use generic views in django, ListView would be fine here.

simplylizz
  • 1,686
  • 14
  • 28
0

Here we using get_page() to get page wise data(1 page contain 25 data).I would suggest for this like :

def listing(request):
    contact_list = Contacts.objects.all()
    paginator = Paginator(contact_list, 25) # Show 25 contacts per page
    page = request.GET.get('page')
    contacts = paginator.get_page(page)

    return render_to_response('list.html', {"contacts": contacts})
Riyas Ac
  • 1,553
  • 1
  • 9
  • 23