Ticket #2367: 5992-pagination-for-datebased-generic-views.diff

File 5992-pagination-for-datebased-generic-views.diff, 16.4 KB (added by Øyvind Saltvik <oyvind@…>, 8 years ago)

removed Http404 dependency in pagination.py, reraised InvalidPage, wrapped compute_pagination in a try except, use count instead of len on queryset.

  • django/core/paginator.py

     
    8686
    8787    hits = property(_get_hits)
    8888    pages = property(_get_pages)
     89
     90def compute_pagination(paginator, page, paginate_by, allow_empty):
     91    """
     92    Compute queryset considering pagination, and update the context.
     93    """
     94    try:
     95        page = int(page)
     96        queryset = paginator.get_page(page - 1)
     97    except (InvalidPage, ValueError):
     98        if page == 1 and allow_empty:
     99            queryset = paginator.query_set.empty()
     100        else:
     101            raise InvalidPage
     102
     103    c = {}
     104    c['is_paginated'] = paginator.pages > 1
     105    c['results_per_page'] = paginate_by
     106    c['has_next'] = paginator.has_next_page(page - 1)
     107    c['has_previous'] = paginator.has_previous_page(page - 1)
     108    c['page'] = page
     109    c['next'] = page + 1
     110    c['previous'] = page - 1
     111    c['last_on_page'] = paginator.last_on_page(page - 1),
     112    c['first_on_page'] = paginator.first_on_page(page - 1),
     113    c['pages'] = paginator.pages
     114    c['hits'] = paginator.hits
     115
     116    return (queryset, c)
  • django/views/generic/date_based.py

     
    11from django.template import loader, RequestContext
    22from django.core.exceptions import ObjectDoesNotExist
    33from django.core.xheaders import populate_xheaders
     4from django.core.paginator import compute_pagination, ObjectPaginator, InvalidPage
    45from django.db.models.fields import DateTimeField
    56from django.http import Http404, HttpResponse
    67import datetime, time
     
    89def archive_index(request, queryset, date_field, num_latest=15,
    910        template_name=None, template_loader=loader,
    1011        extra_context=None, allow_empty=False, context_processors=None,
    11         mimetype=None, allow_future=False):
     12        mimetype=None, allow_future=False, paginate_by=None, page=None):
    1213    """
    1314    Generic top-level archive of date-based objects.
    1415
     
    1819            List of years
    1920        latest
    2021            Latest N (defaults to 15) objects by date
     22        is_paginated
     23            are the results paginated?
     24        results_per_page
     25            number of objects per page (if paginated)
     26        has_next
     27            is there a next page?
     28        has_previous
     29            is there a prev page?
     30        page
     31            the current page
     32        next
     33            the next page
     34        previous
     35            the previous page
     36        pages
     37            number of pages, total
     38        hits
     39            number of objects, total
     40        last_on_page
     41            the result number of the last of object in the
     42            object_list (1-indexed)
     43        first_on_page
     44            the result number of the first object in the
     45            object_list (1-indexed)
    2146    """
    2247    if extra_context is None: extra_context = {}
    2348    model = queryset.model
     
    3055    if date_list and num_latest:
    3156        latest = queryset.order_by('-'+date_field)[:num_latest]
    3257    else:
    33         latest = None
     58        latest = []
    3459
     60    # Pagination.
     61    pagination_context = {'is_paginated': False}
     62    if paginate_by:
     63        paginator = ObjectPaginator(latest, paginate_by)
     64        page = page or request.GET.get('page', 1)
     65        try:
     66            latest, pagination_context = compute_pagination(paginator, page, paginate_by, allow_empty)
     67        except InvalidPage:
     68            raise Http404
     69
    3570    if not template_name:
    3671        template_name = "%s/%s_archive.html" % (model._meta.app_label, model._meta.object_name.lower())
    3772    t = template_loader.get_template(template_name)
     
    4479            c[key] = value()
    4580        else:
    4681            c[key] = value
     82
     83    c.update(pagination_context)
     84
    4785    return HttpResponse(t.render(c), mimetype=mimetype)
    4886
    4987def archive_year(request, year, queryset, date_field, template_name=None,
    5088        template_loader=loader, extra_context=None, allow_empty=False,
    5189        context_processors=None, template_object_name='object', mimetype=None,
    52         make_object_list=False, allow_future=False):
     90        make_object_list=False, allow_future=False, paginate_by=None, page=None):
    5391    """
    5492    Generic yearly archive view.
    5593
     
    6199            This year
    62100        object_list
    63101            List of objects published in the given month
     102
    64103            (Only available if make_object_list argument is True)
     104
     105        is_paginated
     106            are the results paginated?
     107        results_per_page
     108            number of objects per page (if paginated)
     109        has_next
     110            is there a next page?
     111        has_previous
     112            is there a prev page?
     113        page
     114            the current page
     115        next
     116            the next page
     117        previous
     118            the previous page
     119        pages
     120            number of pages, total
     121        hits
     122            number of objects, total
     123        last_on_page
     124            the result number of the last of object in the
     125            object_list (1-indexed)
     126        first_on_page
     127            the result number of the first object in the
     128            object_list (1-indexed)
    65129    """
    66130    if extra_context is None: extra_context = {}
    67131    model = queryset.model
     
    79143        object_list = queryset.filter(**lookup_kwargs).order_by(date_field)
    80144    else:
    81145        object_list = []
     146
     147    # Pagination.
     148    pagination_context = {'is_paginated': False}
     149    if paginate_by:
     150        paginator = ObjectPaginator(object_list, paginate_by)
     151        page = page or request.GET.get('page', 1)
     152        try:
     153            object_list, pagination_context = compute_pagination(paginator, page, paginate_by, allow_empty)
     154        except InvalidPage:
     155            raise Http404
     156
    82157    if not template_name:
    83158        template_name = "%s/%s_archive_year.html" % (model._meta.app_label, model._meta.object_name.lower())
    84159    t = template_loader.get_template(template_name)
     
    92167            c[key] = value()
    93168        else:
    94169            c[key] = value
     170
     171    c.update(pagination_context)
     172
    95173    return HttpResponse(t.render(c), mimetype=mimetype)
    96174
    97175def archive_month(request, year, month, queryset, date_field,
    98176        month_format='%b', template_name=None, template_loader=loader,
    99177        extra_context=None, allow_empty=False, context_processors=None,
    100         template_object_name='object', mimetype=None, allow_future=False):
     178        template_object_name='object', mimetype=None, allow_future=False,
     179        paginate_by=None, page=None):
    101180    """
    102181    Generic monthly archive view.
    103182
     
    111190            (date) the first day of the previous month
    112191        object_list:
    113192            list of objects published in the given month
     193        is_paginated
     194            are the results paginated?
     195        results_per_page
     196            number of objects per page (if paginated)
     197        has_next
     198            is there a next page?
     199        has_previous
     200            is there a prev page?
     201        page
     202            the current page
     203        next
     204            the next page
     205        previous
     206            the previous page
     207        pages
     208            number of pages, total
     209        hits
     210            number of objects, total
     211        last_on_page
     212            the result number of the last of object in the
     213            object_list (1-indexed)
     214        first_on_page
     215            the result number of the first object in the
     216            object_list (1-indexed)
    114217    """
    115218    if extra_context is None: extra_context = {}
    116219    try:
     
    144247    else:
    145248        next_month = None
    146249
     250    # Pagination.
     251    pagination_context = {'is_paginated': False}
     252    if paginate_by:
     253        paginator = ObjectPaginator(object_list, paginate_by)
     254        page = page or request.GET.get('page', 1)
     255        try:
     256            object_list, pagination_context = compute_pagination(paginator, page, paginate_by, allow_empty)
     257        except InvalidPage:
     258            raise Http404
     259
    147260    if not template_name:
    148261        template_name = "%s/%s_archive_month.html" % (model._meta.app_label, model._meta.object_name.lower())
    149262    t = template_loader.get_template(template_name)
     
    158271            c[key] = value()
    159272        else:
    160273            c[key] = value
     274
     275    c.update(pagination_context)
     276
    161277    return HttpResponse(t.render(c), mimetype=mimetype)
    162278
    163279def archive_week(request, year, week, queryset, date_field,
    164280        template_name=None, template_loader=loader,
    165281        extra_context=None, allow_empty=True, context_processors=None,
    166         template_object_name='object', mimetype=None, allow_future=False):
     282        template_object_name='object', mimetype=None, allow_future=False,
     283        paginate_by=None, page=None):
    167284    """
    168285    Generic weekly archive view.
    169286
     
    173290            (date) this week
    174291        object_list:
    175292            list of objects published in the given week
     293        is_paginated
     294            are the results paginated?
     295        results_per_page
     296            number of objects per page (if paginated)
     297        has_next
     298            is there a next page?
     299        has_previous
     300            is there a prev page?
     301        page
     302            the current page
     303        next
     304            the next page
     305        previous
     306            the previous page
     307        pages
     308            number of pages, total
     309        hits
     310            number of objects, total
     311        last_on_page
     312            the result number of the last of object in the
     313            object_list (1-indexed)
     314        first_on_page
     315            the result number of the first object in the
     316            object_list (1-indexed)
    176317    """
    177318    if extra_context is None: extra_context = {}
    178319    try:
     
    194335    object_list = queryset.filter(**lookup_kwargs)
    195336    if not object_list and not allow_empty:
    196337        raise Http404
     338
     339    # Pagination.
     340    pagination_context = {'is_paginated': False}
     341    if paginate_by:
     342        paginator = ObjectPaginator(object_list, paginate_by)
     343        page = page or request.GET.get('page', 1)
     344        try:
     345            object_list, pagination_context = compute_pagination(paginator, page, paginate_by, allow_empty)
     346        except InvalidPage:
     347            raise Http404
     348
    197349    if not template_name:
    198350        template_name = "%s/%s_archive_week.html" % (model._meta.app_label, model._meta.object_name.lower())
    199351    t = template_loader.get_template(template_name)
     
    206358            c[key] = value()
    207359        else:
    208360            c[key] = value
     361
     362    c.update(pagination_context)
     363
    209364    return HttpResponse(t.render(c), mimetype=mimetype)
    210365
    211366def archive_day(request, year, month, day, queryset, date_field,
    212367        month_format='%b', day_format='%d', template_name=None,
    213368        template_loader=loader, extra_context=None, allow_empty=False,
    214369        context_processors=None, template_object_name='object',
    215         mimetype=None, allow_future=False):
     370        mimetype=None, allow_future=False, paginate_by=None, page=None):
    216371    """
    217372    Generic daily archive view.
    218373
     
    226381            (datetime) the previous day
    227382        next_day
    228383            (datetime) the next day, or None if the current day is today
     384        is_paginated
     385            are the results paginated?
     386        results_per_page
     387            number of objects per page (if paginated)
     388        has_next
     389            is there a next page?
     390        has_previous
     391            is there a prev page?
     392        page
     393            the current page
     394        next
     395            the next page
     396        previous
     397            the previous page
     398        pages
     399            number of pages, total
     400        hits
     401            number of objects, total
     402        last_on_page
     403            the result number of the last of object in the
     404            object_list (1-indexed)
     405        first_on_page
     406            the result number of the first object in the
     407            object_list (1-indexed)
    229408    """
    230409    if extra_context is None: extra_context = {}
    231410    try:
     
    256435    else:
    257436        next_day = None
    258437
     438    # Pagination.
     439    pagination_context = {'is_paginated': False}
     440    if paginate_by:
     441        paginator = ObjectPaginator(object_list, paginate_by)
     442        page = page or request.GET.get('page', 1)
     443        try:
     444            object_list, pagination_context = compute_pagination(paginator, page, paginate_by, allow_empty)
     445        except InvalidPage:
     446            raise Http404
     447
    259448    if not template_name:
    260449        template_name = "%s/%s_archive_day.html" % (model._meta.app_label, model._meta.object_name.lower())
    261450    t = template_loader.get_template(template_name)
     
    270459            c[key] = value()
    271460        else:
    272461            c[key] = value
     462
     463    c.update(pagination_context)
     464
    273465    return HttpResponse(t.render(c), mimetype=mimetype)
    274466
    275467def archive_today(request, **kwargs):
     
    288480        month_format='%b', day_format='%d', object_id=None, slug=None,
    289481        slug_field='slug', template_name=None, template_name_field=None,
    290482        template_loader=loader, extra_context=None, context_processors=None,
    291         template_object_name='object', mimetype=None, allow_future=False):
     483        template_object_name='object', mimetype=None, allow_future=False, page=None):
    292484    """
    293485    Generic detail view from year/month/day/slug or year/month/day/id structure.
    294486
     
    333525        t = template_loader.get_template(template_name)
    334526    c = RequestContext(request, {
    335527        template_object_name: obj,
     528        page: page
    336529    }, context_processors)
    337530    for key, value in extra_context.items():
    338531        if callable(value):
  • django/views/generic/list_detail.py

     
    11from django.template import loader, RequestContext
    22from django.http import Http404, HttpResponse
    33from django.core.xheaders import populate_xheaders
    4 from django.core.paginator import ObjectPaginator, InvalidPage
     4from django.core.paginator import compute_pagination, ObjectPaginator, InvalidPage
    55from django.core.exceptions import ObjectDoesNotExist
    66
    77def object_list(request, queryset, paginate_by=None, page=None,
     
    4242    """
    4343    if extra_context is None: extra_context = {}
    4444    queryset = queryset._clone()
     45
     46    if not allow_empty and queryset.count() == 0:
     47        raise Http404
     48
     49    # Pagination.
     50    pagination_context = {'is_paginated': False}
    4551    if paginate_by:
    4652        paginator = ObjectPaginator(queryset, paginate_by)
    47         if not page:
    48             page = request.GET.get('page', 1)
     53        page = page or request.GET.get('page', 1)
    4954        try:
    50             page = int(page)
    51             object_list = paginator.get_page(page - 1)
    52         except (InvalidPage, ValueError):
    53             if page == 1 and allow_empty:
    54                 object_list = []
    55             else:
    56                 raise Http404
    57         c = RequestContext(request, {
    58             '%s_list' % template_object_name: object_list,
    59             'is_paginated': paginator.pages > 1,
    60             'results_per_page': paginate_by,
    61             'has_next': paginator.has_next_page(page - 1),
    62             'has_previous': paginator.has_previous_page(page - 1),
    63             'page': page,
    64             'next': page + 1,
    65             'previous': page - 1,
    66             'last_on_page': paginator.last_on_page(page - 1),
    67             'first_on_page': paginator.first_on_page(page - 1),
    68             'pages': paginator.pages,
    69             'hits' : paginator.hits,
    70         }, context_processors)
    71     else:
    72         c = RequestContext(request, {
    73             '%s_list' % template_object_name: queryset,
    74             'is_paginated': False
    75         }, context_processors)
    76         if not allow_empty and len(queryset) == 0:
     55            queryset, pagination_context = compute_pagination(paginator, page, paginate_by, allow_empty)
     56        except InvalidPage:
    7757            raise Http404
     58    c = RequestContext(request, {
     59        '%s_list' % template_object_name: queryset,
     60    }, context_processors)
    7861    for key, value in extra_context.items():
    7962        if callable(value):
    8063            c[key] = value()
    8164        else:
    8265            c[key] = value
     66
     67    c.update(pagination_context)
     68
    8369    if not template_name:
    8470        model = queryset.model
    8571        template_name = "%s/%s_list.html" % (model._meta.app_label, model._meta.object_name.lower())
Back to Top