Index: date_based.py
===================================================================
--- date_based.py	(revision 4741)
+++ date_based.py	(working copy)
@@ -1,14 +1,45 @@
 from django.template import loader, RequestContext
 from django.core.exceptions import ObjectDoesNotExist
 from django.core.xheaders import populate_xheaders
+from django.core.paginator import ObjectPaginator, InvalidPage
 from django.db.models.fields import DateTimeField
 from django.http import Http404, HttpResponse
 import datetime, time
 
+def compute_pagination(request, paginator, page, paginate_by):
+    """
+    Compute queryset considering pagination, and update the context.
+    """
+    if not page:
+        page = request.GET.get('page', 1)
+    try:
+        page = int(page)
+        queryset = paginator.get_page(page - 1)
+    except (InvalidPage, ValueError):
+        if page == 1 and allow_empty:
+            queryset = []
+        else:
+            raise Http404
+
+    c = {}
+    c['is_paginated'] = paginator.pages > 1
+    c['results_per_page'] = paginate_by
+    c['has_next'] = paginator.has_next_page(page - 1)
+    c['has_previous'] = paginator.has_previous_page(page - 1)
+    c['page'] = page
+    c['next'] = page + 1
+    c['previous'] = page - 1
+    c['last_on_page'] = paginator.last_on_page(page - 1),
+    c['first_on_page'] = paginator.first_on_page(page - 1),
+    c['pages'] = paginator.pages
+    c['hits'] = paginator.hits
+
+    return (queryset, c)
+
 def archive_index(request, queryset, date_field, num_latest=15,
         template_name=None, template_loader=loader,
         extra_context=None, allow_empty=False, context_processors=None,
-        mimetype=None, allow_future=False):
+        mimetype=None, allow_future=False, paginate_by=None, page=None):
     """
     Generic top-level archive of date-based objects.
 
@@ -18,6 +49,30 @@
             List of years
         latest
             Latest N (defaults to 15) objects by date
+        is_paginated
+            are the results paginated?
+        results_per_page
+            number of objects per page (if paginated)
+        has_next
+            is there a next page?
+        has_previous
+            is there a prev page?
+        page
+            the current page
+        next
+            the next page
+        previous
+            the previous page
+        pages
+            number of pages, total
+        hits
+            number of objects, total
+        last_on_page
+            the result number of the last of object in the
+            object_list (1-indexed)
+        first_on_page
+            the result number of the first object in the
+            object_list (1-indexed)
     """
     if extra_context is None: extra_context = {}
     model = queryset.model
@@ -30,8 +85,14 @@
     if date_list and num_latest:
         latest = queryset.order_by('-'+date_field)[:num_latest]
     else:
-        latest = None
+        latest = []
 
+    # Pagination.
+    pagination_context = {'is_paginated': False}
+    if paginate_by:
+        paginator = ObjectPaginator(latest, paginate_by)
+        latest, pagination_context = compute_pagination(request, paginator, page, paginate_by)
+
     if not template_name:
         template_name = "%s/%s_archive.html" % (model._meta.app_label, model._meta.object_name.lower())
     t = template_loader.get_template(template_name)
@@ -44,12 +105,15 @@
             c[key] = value()
         else:
             c[key] = value
+
+    c.update(pagination_context)
+
     return HttpResponse(t.render(c), mimetype=mimetype)
 
 def archive_year(request, year, queryset, date_field, template_name=None,
         template_loader=loader, extra_context=None, allow_empty=False,
         context_processors=None, template_object_name='object', mimetype=None,
-        make_object_list=False, allow_future=False):
+        make_object_list=False, allow_future=False, paginate_by=None, page=None):
     """
     Generic yearly archive view.
 
@@ -61,7 +125,33 @@
             This year
         object_list
             List of objects published in the given month
+
             (Only available if make_object_list argument is True)
+
+        is_paginated
+            are the results paginated?
+        results_per_page
+            number of objects per page (if paginated)
+        has_next
+            is there a next page?
+        has_previous
+            is there a prev page?
+        page
+            the current page
+        next
+            the next page
+        previous
+            the previous page
+        pages
+            number of pages, total
+        hits
+            number of objects, total
+        last_on_page
+            the result number of the last of object in the
+            object_list (1-indexed)
+        first_on_page
+            the result number of the first object in the
+            object_list (1-indexed)
     """
     if extra_context is None: extra_context = {}
     model = queryset.model
@@ -79,6 +169,13 @@
         object_list = queryset.filter(**lookup_kwargs).order_by(date_field)
     else:
         object_list = []
+
+    # Pagination.
+    pagination_context = {'is_paginated': False}
+    if paginate_by:
+        paginator = ObjectPaginator(object_list, paginate_by)
+        object_list, pagination_context = compute_pagination(request, paginator, page, paginate_by)
+
     if not template_name:
         template_name = "%s/%s_archive_year.html" % (model._meta.app_label, model._meta.object_name.lower())
     t = template_loader.get_template(template_name)
@@ -92,12 +189,16 @@
             c[key] = value()
         else:
             c[key] = value
+
+    c.update(pagination_context)
+
     return HttpResponse(t.render(c), mimetype=mimetype)
 
 def archive_month(request, year, month, queryset, date_field,
         month_format='%b', template_name=None, template_loader=loader,
         extra_context=None, allow_empty=False, context_processors=None,
-        template_object_name='object', mimetype=None, allow_future=False):
+        template_object_name='object', mimetype=None, allow_future=False,
+        paginate_by=None, page=None):
     """
     Generic monthly archive view.
 
@@ -111,6 +212,30 @@
             (date) the first day of the previous month
         object_list:
             list of objects published in the given month
+        is_paginated
+            are the results paginated?
+        results_per_page
+            number of objects per page (if paginated)
+        has_next
+            is there a next page?
+        has_previous
+            is there a prev page?
+        page
+            the current page
+        next
+            the next page
+        previous
+            the previous page
+        pages
+            number of pages, total
+        hits
+            number of objects, total
+        last_on_page
+            the result number of the last of object in the
+            object_list (1-indexed)
+        first_on_page
+            the result number of the first object in the
+            object_list (1-indexed)
     """
     if extra_context is None: extra_context = {}
     try:
@@ -144,6 +269,12 @@
     else:
         next_month = None
 
+    # Pagination.
+    pagination_context = {'is_paginated': False}
+    if paginate_by:
+        paginator = ObjectPaginator(object_list, paginate_by)
+        object_list, pagination_context = compute_pagination(request, paginator, page, paginate_by)
+
     if not template_name:
         template_name = "%s/%s_archive_month.html" % (model._meta.app_label, model._meta.object_name.lower())
     t = template_loader.get_template(template_name)
@@ -158,12 +289,16 @@
             c[key] = value()
         else:
             c[key] = value
+
+    c.update(pagination_context)
+
     return HttpResponse(t.render(c), mimetype=mimetype)
 
 def archive_week(request, year, week, queryset, date_field,
         template_name=None, template_loader=loader,
         extra_context=None, allow_empty=True, context_processors=None,
-        template_object_name='object', mimetype=None, allow_future=False):
+        template_object_name='object', mimetype=None, allow_future=False,
+        paginate_by=None, page=None):
     """
     Generic weekly archive view.
 
@@ -173,6 +308,30 @@
             (date) this week
         object_list:
             list of objects published in the given week
+        is_paginated
+            are the results paginated?
+        results_per_page
+            number of objects per page (if paginated)
+        has_next
+            is there a next page?
+        has_previous
+            is there a prev page?
+        page
+            the current page
+        next
+            the next page
+        previous
+            the previous page
+        pages
+            number of pages, total
+        hits
+            number of objects, total
+        last_on_page
+            the result number of the last of object in the
+            object_list (1-indexed)
+        first_on_page
+            the result number of the first object in the
+            object_list (1-indexed)
     """
     if extra_context is None: extra_context = {}
     try:
@@ -194,6 +353,13 @@
     object_list = queryset.filter(**lookup_kwargs)
     if not object_list and not allow_empty:
         raise Http404
+
+    # Pagination.
+    pagination_context = {'is_paginated': False}
+    if paginate_by:
+        paginator = ObjectPaginator(object_list, paginate_by)
+        object_list, pagination_context = compute_pagination(request, paginator, page, paginate_by)
+
     if not template_name:
         template_name = "%s/%s_archive_week.html" % (model._meta.app_label, model._meta.object_name.lower())
     t = template_loader.get_template(template_name)
@@ -206,13 +372,16 @@
             c[key] = value()
         else:
             c[key] = value
+
+    c.update(pagination_context)
+
     return HttpResponse(t.render(c), mimetype=mimetype)
 
 def archive_day(request, year, month, day, queryset, date_field,
         month_format='%b', day_format='%d', template_name=None,
         template_loader=loader, extra_context=None, allow_empty=False,
         context_processors=None, template_object_name='object',
-        mimetype=None, allow_future=False):
+        mimetype=None, allow_future=False, paginate_by=None, page=None):
     """
     Generic daily archive view.
 
@@ -226,6 +395,30 @@
             (datetime) the previous day
         next_day
             (datetime) the next day, or None if the current day is today
+        is_paginated
+            are the results paginated?
+        results_per_page
+            number of objects per page (if paginated)
+        has_next
+            is there a next page?
+        has_previous
+            is there a prev page?
+        page
+            the current page
+        next
+            the next page
+        previous
+            the previous page
+        pages
+            number of pages, total
+        hits
+            number of objects, total
+        last_on_page
+            the result number of the last of object in the
+            object_list (1-indexed)
+        first_on_page
+            the result number of the first object in the
+            object_list (1-indexed)
     """
     if extra_context is None: extra_context = {}
     try:
@@ -256,6 +449,12 @@
     else:
         next_day = None
 
+    # Pagination.
+    pagination_context = {'is_paginated': False}
+    if paginate_by:
+        paginator = ObjectPaginator(object_list, paginate_by)
+        object_list, pagination_context = compute_pagination(request, paginator, page, paginate_by)
+
     if not template_name:
         template_name = "%s/%s_archive_day.html" % (model._meta.app_label, model._meta.object_name.lower())
     t = template_loader.get_template(template_name)
@@ -270,6 +469,9 @@
             c[key] = value()
         else:
             c[key] = value
+
+    c.update(pagination_context)
+
     return HttpResponse(t.render(c), mimetype=mimetype)
 
 def archive_today(request, **kwargs):
