Django之分页器

2019-05-13  本文已影响0人  _Cappuccino_

Django自带分页器的实现

介绍

Django提供了一个新的类来帮助你管理分页数据,这个模块存放在django.core.paginator.py。
其中有两个核心类,一个是Paginator类,另一个是Page类。

Paginator类
初始化操作
class Paginator(object):
    def __init__(self, object_list, per_page, orphans=0, allow_empty_first_page=True):
        self.object_list = object_list
        self.per_page = int(per_page)
        self.orphans = int(orphans)
        self.allow_empty_first_page = allow_empty_first_page
        self._num_pages = self._count = None

解释:

类方法:
类属型:
Page类
初始化操作
class Page(collections.Sequence):
    def __init__(self, object_list, number, paginator):
        self.object_list = object_list
        self.number = number
        self.paginator = paginator
类方法
类属型
异常处理
使用方式
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from django.shortcuts import render

def listing(request):
    contact_list = Contacts.objects.all()  # 获取所有contacts,假设在models.py中已定义了Contacts模型
    paginator = Paginator(contact_list, 25) # 每页25条
    page = request.GET.get('page')
    try:
        contacts = paginator.page(page) # contacts为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(request, 'list.html', {'contacts': contacts})
{% for contact in contacts %}
    {# Each "contact" is a Contact model object. #}
    {{ contact.full_name|upper }}<br />
    ...
{% endfor %}

<div class="pagination">
    <span class="step-links">
        {% if contacts.has_previous %}
            <a href="?page={{ contacts.previous_page_number }}">previous</a>
        {% endif %}

        <span class="current">
            Page {{ contacts.number }} of {{ contacts.paginator.num_pages }}.
        </span>

        {% if contacts.has_next %}
            <a href="?page={{ contacts.next_page_number }}">next</a>
        {% endif %}
    </span>
</div>

或者另一种形式

<div id="pagination">
    <ul id="pagination-flickr">
    {% if article_list.has_previous %}
    <li class="previous"><a href="?page={{ article_list.previous_page_number }}{% if request.GET.year %}&year={{ request.GET.year }}{% endif %}{% if request.GET.month %}&month={{ request.GET.month }}{% endif %}{% if request.GET.cid %}&cid={{ request.GET.cid }}{% endif %}">&laquo;上一页</a></li>
    {% else %}
    <li class="previous-off">&laquo;上一页</li>
    {% endif %}

     <li class="active">{{ article_list.number }}/{{ article_list.paginator.num_pages }}</li>
    {% if article_list.has_next %}
      <li class="next"><a href="?page={{ article_list.next_page_number }}{% if request.GET.year %}&year={{ request.GET.year }}{% endif %}{% if request.GET.month %}&month={{ request.GET.month }}{% endif %}{% if request.GET.cid %}&cid={{ request.GET.cid }}{% endif %}">下一页 &raquo;</a></li>
    {% else %}
      <li class="next-off">下一页 &raquo;</li>
    {% endif %}
   </ul>
</div>
存在问题
描述

上面这种分页方式,在数据量较小的时候是没有效率问题,但是随着数据量的不断增大,查询速度越来越慢。


Django分页器优化的实现

原理

利用Django查询集的惰性查询特性

实现
def owner_page(request, obj):
    """
    # 自定义分页器
    :param request: request请求
    :param obj: 分页对象
    :return: 所在页码的对象集,所有页码,当前页码,分页对象的总数
    """
    current_page = 1
    all_page = 1
    page_type = ''
    try:
        current_page = int(request.GET.get('cur', '1'))
        all_page = int(request.GET.get('all', '1'))
        page_type = str(request.GET.get('action', ''))  # 向前翻页还是向下翻页
    except ValueError:
        current_page = 1
        all_page = 1
        page_type = ''

    if page_type == 'next':
        current_page += 1
    elif page_type == 'previous':
        current_page -= 1
    if isinstance(obj, list):
        count = len(obj)
    else:
        count = obj.count()
    start = (current_page - 1) * PAGE_SIZE
    end = current_page * PAGE_SIZE
    data = obj[start:end]

    if current_page == 1 and current_page == 1:  # 标记1
        all_page = math.ceil(count / PAGE_SIZE)
    return data, all_page, current_page, count
使用方式
def get_all_goods(request):
    user_id = request.session.get('user_id')
    goods = Good.objects.get_user_goods(user_id=user_id)
    data, all_page, current_page, count = owner_page(request, goods)
    return render(
        request,
        "goods_all_list.html",
        {'data': data, 'allPage': all_page, 'curPage': current_page, 'count': count}
    )
<div id="pages" class="text-left">
    <nav>
        <ul class="pagination">
            <li class="step-links">
                {% ifnotequal curPage 1 %}
                <a href="?cur={{ curPage }}&&all={{ allPage }}&&action=previous">
                    上一页
                </a>
                {% endifnotequal %}

                <span class="current">第{{ curPage }}&nbsp;&nbsp;/&nbsp;&nbsp;{{ allPage }}页</span>

                {% ifnotequal curPage allPage %}
                <a href="?cur={{ curPage }}&&all={{ allPage }}&&action=next">
                    下一页
                </a>
                {% endifnotequal %}
            </li>
            <li><span class="[object Object]"
                      style="color:blank;sex:black;border:1px solid #ddd;">共{{ count }}条记录</span></li>
        </ul>
    </nav>
</div>
...
{% include "page.html" %}
...
上一篇 下一篇

猜你喜欢

热点阅读