Ticket #2367: generic_views_pagination.diff

File generic_views_pagination.diff, 15.2 KB (added by paolo@…, 8 years ago)
  • django/core/paginator.py

     
     1from django.http import Http404
     2
    13class InvalidPage(Exception):
    24    pass
    35
     
    8688
    8789    hits = property(_get_hits)
    8890    pages = property(_get_pages)
     91
     92def compute_pagination(paginator, page, paginate_by):
     93    """
     94    Compute queryset considering pagination, and update the context.
     95    """
     96    try:
     97        page = int(page)
     98        queryset = paginator.get_page(page - 1)
     99    except (InvalidPage, ValueError):
     100        if page == 1 and allow_empty:
     101            queryset = []
     102        else:
     103            raise Http404
     104
     105    c = {}
     106    c['is_paginated'] = paginator.pages > 1
     107    c['results_per_page'] = paginate_by
     108    c['has_next'] = paginator.has_next_page(page - 1)
     109    c['has_previous'] = paginator.has_previous_page(page - 1)
     110    c['page'] = page
     111    c['next'] = page + 1
     112    c['previous'] = page - 1
     113    c['last_on_page'] = paginator.last_on_page(page - 1),
     114    c['first_on_page'] = paginator.first_on_page(page - 1),
     115    c['pages'] = paginator.pages
     116    c['hits'] = paginator.hits
     117
     118    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
    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        latest, pagination_context = compute_pagination(paginator, page, paginate_by)
     66
    3567    if not template_name:
    3668        template_name = "%s/%s_archive.html" % (model._meta.app_label, model._meta.object_name.lower())
    3769    t = template_loader.get_template(template_name)
     
    4476            c[key] = value()
    4577        else:
    4678            c[key] = value
     79
     80    c.update(pagination_context)
     81
    4782    return HttpResponse(t.render(c), mimetype=mimetype)
    4883
    4984def archive_year(request, year, queryset, date_field, template_name=None,
    5085        template_loader=loader, extra_context=None, allow_empty=False,
    5186        context_processors=None, template_object_name='object', mimetype=None,
    52         make_object_list=False, allow_future=False):
     87        make_object_list=False, allow_future=False, paginate_by=None, page=None):
    5388    """
    5489    Generic yearly archive view.
    5590
     
    6196            This year
    6297        object_list
    6398            List of objects published in the given month
     99
    64100            (Only available if make_object_list argument is True)
     101
     102        is_paginated
     103            are the results paginated?
     104        results_per_page
     105            number of objects per page (if paginated)
     106        has_next
     107            is there a next page?
     108        has_previous
     109            is there a prev page?
     110        page
     111            the current page
     112        next
     113            the next page
     114        previous
     115            the previous page
     116        pages
     117            number of pages, total
     118        hits
     119            number of objects, total
     120        last_on_page
     121            the result number of the last of object in the
     122            object_list (1-indexed)
     123        first_on_page
     124            the result number of the first object in the
     125            object_list (1-indexed)
    65126    """
    66127    if extra_context is None: extra_context = {}
    67128    model = queryset.model
     
    79140        object_list = queryset.filter(**lookup_kwargs).order_by(date_field)
    80141    else:
    81142        object_list = []
     143
     144    # Pagination.
     145    pagination_context = {'is_paginated': False}
     146    if paginate_by:
     147        paginator = ObjectPaginator(object_list, paginate_by)
     148        page = page or request.GET.get('page', 1)
     149        object_list, pagination_context = compute_pagination(paginator, page, paginate_by)
     150
    82151    if not template_name:
    83152        template_name = "%s/%s_archive_year.html" % (model._meta.app_label, model._meta.object_name.lower())
    84153    t = template_loader.get_template(template_name)
     
    92161            c[key] = value()
    93162        else:
    94163            c[key] = value
     164
     165    c.update(pagination_context)
     166
    95167    return HttpResponse(t.render(c), mimetype=mimetype)
    96168
    97169def archive_month(request, year, month, queryset, date_field,
    98170        month_format='%b', template_name=None, template_loader=loader,
    99171        extra_context=None, allow_empty=False, context_processors=None,
    100         template_object_name='object', mimetype=None, allow_future=False):
     172        template_object_name='object', mimetype=None, allow_future=False,
     173        paginate_by=None, page=None):
    101174    """
    102175    Generic monthly archive view.
    103176
     
    111184            (date) the first day of the previous month
    112185        object_list:
    113186            list of objects published in the given month
     187        is_paginated
     188            are the results paginated?
     189        results_per_page
     190            number of objects per page (if paginated)
     191        has_next
     192            is there a next page?
     193        has_previous
     194            is there a prev page?
     195        page
     196            the current page
     197        next
     198            the next page
     199        previous
     200            the previous page
     201        pages
     202            number of pages, total
     203        hits
     204            number of objects, total
     205        last_on_page
     206            the result number of the last of object in the
     207            object_list (1-indexed)
     208        first_on_page
     209            the result number of the first object in the
     210            object_list (1-indexed)
    114211    """
    115212    if extra_context is None: extra_context = {}
    116213    try:
     
    144241    else:
    145242        next_month = None
    146243
     244    # Pagination.
     245    pagination_context = {'is_paginated': False}
     246    if paginate_by:
     247        paginator = ObjectPaginator(object_list, paginate_by)
     248        page = page or request.GET.get('page', 1)
     249        object_list, pagination_context = compute_pagination(paginator, page, paginate_by)
     250
    147251    if not template_name:
    148252        template_name = "%s/%s_archive_month.html" % (model._meta.app_label, model._meta.object_name.lower())
    149253    t = template_loader.get_template(template_name)
     
    158262            c[key] = value()
    159263        else:
    160264            c[key] = value
     265
     266    c.update(pagination_context)
     267
    161268    return HttpResponse(t.render(c), mimetype=mimetype)
    162269
    163270def archive_week(request, year, week, queryset, date_field,
    164271        template_name=None, template_loader=loader,
    165272        extra_context=None, allow_empty=True, context_processors=None,
    166         template_object_name='object', mimetype=None, allow_future=False):
     273        template_object_name='object', mimetype=None, allow_future=False,
     274        paginate_by=None, page=None):
    167275    """
    168276    Generic weekly archive view.
    169277
     
    173281            (date) this week
    174282        object_list:
    175283            list of objects published in the given week
     284        is_paginated
     285            are the results paginated?
     286        results_per_page
     287            number of objects per page (if paginated)
     288        has_next
     289            is there a next page?
     290        has_previous
     291            is there a prev page?
     292        page
     293            the current page
     294        next
     295            the next page
     296        previous
     297            the previous page
     298        pages
     299            number of pages, total
     300        hits
     301            number of objects, total
     302        last_on_page
     303            the result number of the last of object in the
     304            object_list (1-indexed)
     305        first_on_page
     306            the result number of the first object in the
     307            object_list (1-indexed)
    176308    """
    177309    if extra_context is None: extra_context = {}
    178310    try:
     
    194326    object_list = queryset.filter(**lookup_kwargs)
    195327    if not object_list and not allow_empty:
    196328        raise Http404
     329
     330    # Pagination.
     331    pagination_context = {'is_paginated': False}
     332    if paginate_by:
     333        paginator = ObjectPaginator(object_list, paginate_by)
     334        page = page or request.GET.get('page', 1)
     335        object_list, pagination_context = compute_pagination(paginator, page, paginate_by)
     336
    197337    if not template_name:
    198338        template_name = "%s/%s_archive_week.html" % (model._meta.app_label, model._meta.object_name.lower())
    199339    t = template_loader.get_template(template_name)
     
    206346            c[key] = value()
    207347        else:
    208348            c[key] = value
     349
     350    c.update(pagination_context)
     351
    209352    return HttpResponse(t.render(c), mimetype=mimetype)
    210353
    211354def archive_day(request, year, month, day, queryset, date_field,
    212355        month_format='%b', day_format='%d', template_name=None,
    213356        template_loader=loader, extra_context=None, allow_empty=False,
    214357        context_processors=None, template_object_name='object',
    215         mimetype=None, allow_future=False):
     358        mimetype=None, allow_future=False, paginate_by=None, page=None):
    216359    """
    217360    Generic daily archive view.
    218361
     
    226369            (datetime) the previous day
    227370        next_day
    228371            (datetime) the next day, or None if the current day is today
     372        is_paginated
     373            are the results paginated?
     374        results_per_page
     375            number of objects per page (if paginated)
     376        has_next
     377            is there a next page?
     378        has_previous
     379            is there a prev page?
     380        page
     381            the current page
     382        next
     383            the next page
     384        previous
     385            the previous page
     386        pages
     387            number of pages, total
     388        hits
     389            number of objects, total
     390        last_on_page
     391            the result number of the last of object in the
     392            object_list (1-indexed)
     393        first_on_page
     394            the result number of the first object in the
     395            object_list (1-indexed)
    229396    """
    230397    if extra_context is None: extra_context = {}
    231398    try:
     
    256423    else:
    257424        next_day = None
    258425
     426    # Pagination.
     427    pagination_context = {'is_paginated': False}
     428    if paginate_by:
     429        paginator = ObjectPaginator(object_list, paginate_by)
     430        page = page or request.GET.get('page', 1)
     431        object_list, pagination_context = compute_pagination(paginator, page, paginate_by)
     432
    259433    if not template_name:
    260434        template_name = "%s/%s_archive_day.html" % (model._meta.app_label, model._meta.object_name.lower())
    261435    t = template_loader.get_template(template_name)
     
    270444            c[key] = value()
    271445        else:
    272446            c[key] = value
     447
     448    c.update(pagination_context)
     449
    273450    return HttpResponse(t.render(c), mimetype=mimetype)
    274451
    275452def archive_today(request, **kwargs):
  • 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
    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 len(queryset) == 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)
    49         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:
    77             raise Http404
     53        page = page or request.GET.get('page', 1)
     54        queryset, pagination_context = compute_pagination(paginator, page, paginate_by)
     55
     56    c = RequestContext(request, {
     57        '%s_list' % template_object_name: queryset,
     58    }, context_processors)
    7859    for key, value in extra_context.items():
    7960        if callable(value):
    8061            c[key] = value()
    8162        else:
    8263            c[key] = value
     64
     65    c.update(pagination_context)
     66
    8367    if not template_name:
    8468        model = queryset.model
    8569        template_name = "%s/%s_list.html" % (model._meta.app_label, model._meta.object_name.lower())
Back to Top