Django 的分页和自定义分页组件

一 自定义分页

后台代码

def index(req):
    data = list(range(999))  # 数据源  以列表示例
    current_page_num = req.GET.get('p', None)  # 获取当前页码
    if not current_page_num:
        current_page_num = 1
    else:
        current_page_num = int(current_page_num)
    all_page_num = 100  # 手动设定的全部页数
    page_info_num = 10  # 手动设定的每页显示条数
    start = (current_page_num - 1) * page_info_num  # 切片开始位置
    end = start + page_info_num  # 切片结束位置
    data_list = data[start:end]  # 切片
    if current_page_num == 1:  # 上一页页码
        after = current_page_num
    else:
        after = current_page_num - 1
    if current_page_num == all_page_num:  # 下一页页码
        next = current_page_num
    else:
        next = current_page_num + 1
    return render(req, 'index.html', locals())

前端代码

<body>
<ul>
    {% for i in data_list %}
        <li>{{ i }}</li>
    {% endfor %}
</ul>
<a href="/index?p={{ after }}">上一页</a>
<a href="/index?p={{ next }}">下一页</a>
</body>

二 Django自带分页组件

后台代码

from django.core.paginator import Paginator, EmptyPage
def index1(req):
    data = list(range(999))  # 数据源  以列表示例
    current_page_num = req.GET.get('p', None)  # 当前页码
    if not current_page_num:
        current_page_num = 1
    else:
        current_page_num = int(current_page_num)
    # 分页器 - -类
    # 实例化产生一个对象
    # 两个参数: object_list:对象列表, per_page: 每页显示的条数
    paginator = Paginator(data, 10)
    # 对象内的属性
    # 数据总条数100条
    print('数据总数量', paginator.count)
    # 总页数 10 页
    print('总页数', paginator.num_pages)
    # 页码数的列表
    print('页码列表', paginator.page_range)
    # 取到第 x= 页, 返回一个Page对象
    current_page = paginator.page(current_page_num)
    # 当前页码内所有的数据
    print('数据列表', current_page.object_list)
    # 是否有下一页
    print('是否有下一页', current_page.has_next())
    # 是否有上一页
    print('是否有上一页', current_page.has_previous())
    # 下一页页码数
    print('下一页的页码', current_page.next_page_number())
    # 上一页的页码数
    print('上一页的页码', current_page.previous_page_number())
    data_list = current_page.object_list  # 当前页面要显示的数据
    if current_page.has_previous():  # 上一页页码
        after = current_page.previous_page_number()
    else:
        after = current_page_num
    if current_page.has_next():  # 下一页页码
        next1 = current_page.next_page_number()
    else:
        next1 = current_page_num
    return render(req, 'index1.html', locals())

前台代码

<body>
<ul>
    {% for i in data_list %}
        <li>{{ i }}</li>
    {% endfor %}
</ul>
<a href="/index1?p={{ after }}">上一页</a>
<a href="/index1?p={{ next1 }}">下一页</a>
</body>

三 扩展Django自带分页组件

后台代码

from django.core.paginator import Paginator, EmptyPage
class my_Paginator(Paginator):
    '''
    继承Django的Paginator类
    扩展功能,添加一个返回当前页页码下表列表
    '''
    def __init__(self, current_page, pages, *args, **kwargs):
        self.current_page_num = current_page  # 当前页码
        self.pages = pages  # 每页页码下标数量
        super(my_Paginator, self).__init__(*args, **kwargs)
    def page_num_range(self):
        '''
        返回当前页页码下表列表
        :return:
        '''
        temp = self.pages // 2
        if self.num_pages < self.pages:
            return range(1, self.num_pages + 1)
        if temp >= self.current_page_num:
            return range(1, self.pages + 1)
        if self.current_page_num >= self.num_pages - temp:
            return range(self.num_pages - self.pages + 1, self.num_pages + 1)
        return range(self.current_page_num - temp, self.current_page_num + temp + 1)
def index2(req):
    data = list(range(100))  # 数据源  以列表示例
    current_page_num = req.GET.get('p', None)  # 当前页码
    if not current_page_num:
        current_page_num = 1
    else:
        current_page_num = int(current_page_num)
    paginator = my_Paginator(current_page_num, 5, data, 10)  # 创建分页对象
    current_page = paginator.page(paginator.current_page_num)  # 获得当前页对象
    data_list = current_page.object_list  # 获得当前页面数据列表
    pages_list = list(paginator.page_num_range())  # 获得当前页面页码下标列表
    if current_page.has_previous():  # 上一页页码
        after = current_page.previous_page_number()
    else:
        after = current_page_num
    if current_page.has_next():  # 下一页页码
        next1 = current_page.next_page_number()
    else:
        next1 = current_page_num
    return render(req, 'index2.html', locals())

前台代码

<body>
<ul>
    {% for i in data_list %}
        <li>{{ i }}</li>
    {% endfor %}
</ul>
<a href="/index2?p={{ after }}">上一页</a>
{% for page in pages_list %}
    {% if page == current_page_num %}
        <a style="font-size: 30px" href=/index2?p={{ page }}>{{ page }}</a>
    {% else %}
        <a href=/index2?p={{ page }}>{{ page }}</a>
    {% endif %}
{% endfor %}
<a href="/index2?p={{ next1 }}">下一页</a>
</body>

四 自定义分页

自定义分页类

class my_Paginator:
    '''
    自定义分页组件
    '''
    def __init__(self, data_list, info_num_page, page_num, current_page_num):
        self.data_list = data_list  # 要分页的数据
        self.info_num_page = info_num_page  # 每页数据的数量
        self.page_num = page_num  # 每页分页下标数量
        self.current_page_num = current_page_num  # 当前页码
        self.start = self.info_num_page * (self.current_page_num - 1)
        self.end = self.info_num_page * self.current_page_num
    @property
    def num_pages(self):
        '''
        返回总页数
        :return:
        '''
        a, b = divmod(len(self.data_list), self.info_num_page)
        if b:
            return a + 1
        return a
    @property
    def current_page_data_list(self):
        '''
        返回当前页的数据列表
        :return:
        '''
        return self.data_list[self.start:self.end]
    @property
    def next_page(self):
        '''
        下一页页码
        :return:
        '''
        if self.current_page_num + 1 >= self.num_pages or self.current_page_num <= 0:
            return self.num_pages
        return self.current_page_num + 1
    @property
    def previous_page(self):
        '''
        上一页页码
        :return:
        '''
        if self.current_page_num - 1 <= 1 or self.current_page_num > self.num_pages:
            return 1
        return self.current_page_num - 1
    @property
    def page_num_range(self):
        '''
        返回当前页下标列表
        :return:
        '''
        temp = self.page_num // 2
        if self.num_pages < self.page_num:
            return range(1, self.num_pages + 1)
        if temp >= self.current_page_num:
            return range(1, self.page_num + 1)
        if self.current_page_num >= self.num_pages - temp:
            return range(self.num_pages - self.page_num + 1, self.num_pages + 1)
        return range(self.current_page_num - temp, self.current_page_num + temp + 1)

后台代码

from app0.Paginator import my_Paginator as my_paginator
def index3(req):
    data = list(range(100))  # 以列表为数据源
    current_page_num = req.GET.get('p', None)  # 当前页码
    if not current_page_num:
        current_page_num = 1
    else:
        current_page_num = int(current_page_num)
    paginator = my_paginator(data, 10, 5, current_page_num)  # 实例自定义分页组件对象
    data_list = paginator.current_page_data_list  # 当前页面数据
    pages_list = paginator.page_num_range  # 当前页面下表列表
    after = paginator.previous_page  # 上一页页码
    next1 = paginator.next_page  # 下一页页码
    return render(req, 'index3.html', locals())

前台代码

<body>
<ul>
    {% for i in data_list %}
        <li>{{ i }}</li>
    {% endfor %}
</ul>
<a href="/index3?p={{ after }}">上一页</a>
{% for page in pages_list %}
    {% if page == current_page_num %}
        <a style="font-size: 30px" href=/index3?p={{ page }}>{{ page }}</a>
    {% else %}
        <a href=/index3?p={{ page }}>{{ page }}</a>
    {% endif %}
{% endfor %}
<a href="/index3?p={{ next1 }}">下一页</a>
</body>

五 raw使用自定义sql语句分页查询

后台代码

from app0.models import m
def index4(req):
    current_page_num = req.GET.get('p', None)  # 当前页码
    if not current_page_num:
        current_page_num = 1
    else:
        current_page_num = int(current_page_num)
    start = (current_page_num - 1) * 10  # 数据起始位置
    info_num = 10  # 获取数据的数量
    data_list = m.objects.raw("select * from app0_m limit %s,%s" % (start, info_num))
    data_len = m.objects.all().count()  # 全部数据数量
    if current_page_num <= 1:  # 上一页页码
        after = current_page_num
    else:
        after = current_page_num - 1
    if current_page_num >= data_len:  # 下一页页码
        next1 = current_page_num
    else:
        next1 = current_page_num + 1
    return render(req, 'index4.html', locals())

前台代码

<body>
<ul>
    {% for i in data_list %}
        <li>{{ i.a }}</li>
    {% endfor %}
</ul>
<a href="/index4?p={{ after }}">上一页</a>
{% for page in pages_list %}
    {% if page == current_page_num %}
        <a style="font-size: 30px" href=/index4?p={{ page }}>{{ page }}</a>
    {% else %}
        <a href=/index4?p={{ page }}>{{ page }}</a>
    {% endif %}
{% endfor %}
<a href="/index4?p={{ next1 }}">下一页</a>
</body>

六 基于第四种方式的优化,减少数据库查询次数,但是一次要获取大量数据

后台代码

# 使用的第四种方法的自定义类
from app0.Paginator import my_Paginator as my_paginator
from django.views import View
class index5(View):
    '''
    为了减少数据库查询次数
    故一次获取全部数据
    只有从url获取不到页码时才会重新查询数据
    为了保存查询到的数据才使用CBV的方式
    '''
    data = m.objects.all()  # 获取全部数据
    def get(self, req):
        current_page_num = req.GET.get('p', None)  # 当前页码
        if not current_page_num:
            self.data = m.objects.all()
            current_page_num = 1
        else:
            current_page_num = int(current_page_num)
        paginator = my_paginator(self.data, 10, 5, current_page_num)  # 使用自定义分页组件实例对象
        data_list = paginator.current_page_data_list  # 当前页的数据
        pages_list = paginator.page_num_range  # 当前页的页码列表
        after = paginator.previous_page  # 上一页页码
        next1 = paginator.next_page  # 下一页页码
        return render(req, 'index5.html', locals())

前台代码

<body>
<ul>
    {% for i in data_list %}
        <li>{{ i.a }}</li>
    {% endfor %}
</ul>
<a href="/index5?p={{ after }}">上一页</a>
{% for page in pages_list %}
    {% if page == current_page_num %}
        <a style="font-size: 30px" href=/index5?p={{ page }}>{{ page }}</a>
    {% else %}
        <a href=/index5?p={{ page }}>{{ page }}</a>
    {% endif %}
{% endfor %}
<a href="/index5?p={{ next1 }}">下一页</a>
</body>

七 基于第五种方式的分页优化,并对第四种方式的分页组件修改了一些

基于第四种方式自定义类修改后的类

class my_Paginator1:
    '''
    基于my_Paginator修改了一些功能
    '''
    def __init__(self, data_len, info_num_page, page_num):
        self.data_len = data_len  # 数据长度
        self.info_num_page = info_num_page  # 每页数据的数量
        self.page_num = page_num  # 每页分页下标数量
    def start(self, current_page_num):
        '''
        返回当前页面数据开始位置、页码下标列表
        :param current_page_num:
        :return:
        '''
        temp = self.page_num // 2
        if self.num_pages < self.page_num:
            range_list = list(range(1, self.num_pages + 1))
        elif temp >= current_page_num:
            range_list = list(range(1, self.page_num + 1))
        elif current_page_num >= self.num_pages - temp:
            range_list = list(range(self.num_pages - self.page_num + 1, self.num_pages + 1))
        else:
            range_list = list(range(current_page_num - temp, current_page_num + temp + 1))
        return self.info_num_page * (current_page_num - 1), range_list
    @property
    def num_pages(self):
        '''
        返回总页数
        :return:
        '''
        a, b = divmod(self.data_len, self.info_num_page)
        if b:
            return a + 1
        return a
    @property
    def last_page(self):
        '''
        返回最后一页页码
        :return:
        '''
        return self.num_pages

后台代码

from app0.Paginator import my_Paginator1
class index6(View):
    '''
    为了减少每次从数据库查询到的数据量
    故一次获取全部数据的数量
    只有从url获取不到页码时才会重新查询数据数量
    '''
    data_len = m.objects.count()  # 获取全部数据的条数
    def get(self, req):
        current_page_num = req.GET.get('p', None)  # 当前页码
        if not current_page_num:
            self.data_len = m.objects.count()
            current_page_num = 1
        else:
            current_page_num = int(current_page_num)
        paginator = my_Paginator1(self.data_len, 10, 5)  # 使用修改后的自定义分页组件实例化对象
        start, pages_list = paginator.start(current_page_num)  # 本页数据开始的位置、当前页的页码列表
        data_list = m.objects.raw(
            "select * from app0_m limit %s,%s" % (start, paginator.info_num_page))  # 当前页的数据
        last = paginator.last_page  # 最后一页页码
        return render(req, 'index6.html', locals())

前台代码

<body>
<ul>
    {% for i in data_list %}
        <li>{{ i.a }}</li>
    {% endfor %}
</ul>
<a href="/index6?p=1">第一页</a>
{% for page in pages_list %}
    {% if page == current_page_num %}
        <a style="font-size: 30px" href=/index6?p={{ page }}>{{ page }}</a>
    {% else %}
        <a href=/index6?p={{ page }}>{{ page }}</a>
    {% endif %}
{% endfor %}
<a href="/index6?p={{ last }}">最后一页</a>
</body>

 

posted @ 2018-11-21 22:34  Wuliwawa  阅读(167)  评论(0编辑  收藏  举报