django – 内容分页展示

  • A+
所属分类:Python教程 学编程

一、说明

1.1、分页说明

当数据库中数据有很多,我们通常会在前端页面做分页展示。

分页的数据可以在前端页面实现,也可以在后端实现分页。

后端实现分页的原理就是每次只请求一页数据。

二、分页实现

1.后端函数

def books(request):
    page_num = request.GET.get("page")  # 获取URL参数中的page页码数
    page_num = int(page_num)
    per_page = 10     # 定义每页显示多少条数据
    totle_count = models.Books.objects.all().count()     # 计算总数居的条数
    totle_page, m = divmod(totle_count, per_page)      # 用总数据条数 除以 每页的展示数据条数得到 最大展示多少页
    if m:  # 如果有余数
        totle_page += 1  # 就将最大展示页数+1
    data_start = (page_num - 1) * 10      # 根据页码求当前页的展示条目数开始
    data_end = page_num * 10  # 根据页码求当前页的展示条目数结束
    all_book = models.Books.objects.all()[data_start:data_end]      # 将每页展示的数据赋值给变量(然后将变量传给前端)
    max_page = 9     # 定义页面最多展示多少页码
    half_max_page = max_page // 2       #最多页码数除以2
    page_start = page_num - half_max_page        #页码从哪里开始
    page_end = page_num + half_max_page      #页码到哪里结束
    try:
        page_num = int(page_num)          #将页码数转换int类型
        # 如果输入的页码数超过最大的页码数时,默认返回最后的页面内容
        if page_num >= totle_page:
            page_num = totle_page
    except Exception as e:
        #当页面输入的页码不是数字的时候,默认返回第一页的数据
        page_num = 1

    #页码数的逻辑
    if totle_page < max_page:         #如果总页码数小于最大展示的页码数时
        max_page = totle_page         #最大展示总页码数

    if page_start <=1:         #如果页码开始数值小于等于1
        page_start = 1          #就将开始页码置于1
        page_end = max_page+1    #然后将结束页码设置为最多展示的条目数

    if page_end >= totle_page:    #如果页码的结束数值大于或等于总页面数
        page_end = totle_page     #将页码的结束数值设置为页码的总数
        page_start = totle_page - max_page+1        #然后将页码的开始设置为页码总数减去页面展示的最大页码数

    #每页展示的数据条数逻辑
    html_str_list = []        #定义空列表

    html_str_list.append('<li><a href="/books/?page=1">首页</a></li>')      #添加跳转首页

    if page_num <= 1:       #如果当前页是第一页
        html_str_list.append('<li class="disabled"><a href="#"><span aria-hidden="true">«</span></a></li>')       #就不让继续向前翻页了
    else:      #如果不是第一页
        html_str_list.append('<li><a href="/books/?page={}"><span aria-hidden="true">«</span></a></li>'.format(page_num-1))       #添加上一页

    for i in range(page_start, page_end):         #循环页面总数次,从1开始
        if i == page_num:      #如果是当前页就加一个active类
            tmp = '<li class="active"><a href="/books/?page={0}">{0}</a></li>'.format(i)        #定义html代码
        else:           #如果不是是当前页就显示默认内容
            tmp = '<li><a href="/books/?page={0}">{0}</a></li>'.format(i)  # 定义html代码
        html_str_list.append(tmp)        #将代码追加到列表里

    if page_num >= totle_page:         #如果当前页是最后一页
        html_str_list.append(
                '<li class="disabled"><a href="#"><span aria-hidden="true">»</span></a></li>')  # 就不让继续向后翻页了
    else:    #如果不是最后一页
        html_str_list.append(
        '<li><a href="/books/?page={}"><span aria-hidden="true">»</span></a></li>'.format(page_num + 1))  # 添加下一页

    html_str_list.append('<li><a href="/books/?page={}">尾页</a></li>'.format(totle_page))       #添加跳转尾页

    page_html = "".join(html_str_list)          #字符串拼接

    return render(request,"books.html",{"books":all_book, "page_html": page_html})        #将书籍数和对应的页码传给前端

2.html页面

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">        <!-- 加这个标签,bootstrap自动支持移动端的适配 -->
    <title>书籍列表</title>
    <link rel="stylesheet" href="/static/bootstrap/css/bootstrap.min.css">
</head>
<body>

<table class="table table-bordered table-hover table-striped">
    <thead>
    <tr>
        <th>序号</th>
        <th>ID</th>
        <th>书名</th>
    </tr>
    </thead>
    <tbody>
    {% for book in books %}
        <tr>
            <td>{{ forloop.counter }}</td>
            <td>{{ book.id }}</td>
            <td>{{ book.title }}</td>
        </tr>
    {% endfor %}
    </tbody>
</table>

<nav aria-label="Page navigation" class="text-right">
    <ul class="pagination">
        {{ page_html|safe }}
    </ul>
</nav>

<script src="/static/jquery-3.2.1.min.js"></script>
<script src="/static/bootstrap/js/bootstrap.min.js"></script>

</body>
</html>

三、将分页的代码封装成模块,并实现调用

1.模块封装

class Page():

    def __init__(self, page_num, total_count, url_prefix, per_page=10, max_page=11):
        """

        :param page_num: 当前页码数
        :param total_count: 数据总数
        :param url_prefix: a标签href的前缀
        :param per_page: 每页显示多少条数据
        :param max_page: 页面上最多显示几个页码
        """
        self.url_prefix = url_prefix
        self.max_page = max_page
        # 每一页显示多少条数据
        # 总共需要多少页码来展示
        total_page, m = divmod(total_count, per_page)
        if m:
            total_page += 1
        self.total_page = total_page

        try:
            page_num = int(page_num)
            # 如果输入的页码数超过了最大的页码数,默认返回最后一页
            if page_num > total_page:
                page_num = total_page
        except Exception as e:
            # 当输入的页码不是正经数字的时候 默认返回第一页的数据
            page_num = 1
        self.page_num = page_num

        # 定义两个变量保存数据从哪儿取到哪儿
        self.data_start = (page_num - 1) * 10
        self.data_end = page_num * 10

        # 页面上总共展示多少页码
        if total_page < self.max_page:
            self.max_page = total_page

        half_max_page = self.max_page // 2
        # 页面上展示的页码从哪儿开始
        page_start = page_num - half_max_page
        # 页面上展示的页码到哪儿结束
        page_end = page_num + half_max_page
        # 如果当前页减一半 比1还小
        if page_start <= 1:
            page_start = 1
            page_end = self.max_page
        # 如果 当前页 加 一半 比总页码数还大
        if page_end >= total_page:
            page_end = total_page
            page_start = total_page - self.max_page + 1
        self.page_start = page_start
        self.page_end = page_end

    @property
    def start(self):
        return self.data_start

    @property
    def end(self):
        return self.data_end

    def page_html(self):
        # 自己拼接分页的HTML代码
        html_str_list = []
        # 加上第一页
        html_str_list.append('<li><a href="{}?page=1">首页</a></li>'.format( self.url_prefix))

        # 判断一下 如果是第一页,就没有上一页
        if self.page_num <= 1:
            html_str_list.append('<li class="disabled"><a href="#"><span aria-hidden="true">«</span></a></li>'.format(self.page_num-1))
        else:
            # 加一个上一页的标签
            html_str_list.append('<li><a href="{}?page={}"><span aria-hidden="true">«</span></a></li>'.format( self.url_prefix, self.page_num-1))

        for i in range(self.page_start, self.page_end+1):
            # 如果是当前页就加一个active样式类
            if i == self.page_num:
                tmp = '<li class="active"><a href="{0}?page={1}">{1}</a></li>'.format(self.url_prefix, i)
            else:
                tmp = '<li><a href="{0}?page={1}">{1}</a></li>'.format( self.url_prefix, i)

            html_str_list.append(tmp)

        # 加一个下一页的按钮
        # 判断,如果是最后一页,就没有下一页
        if self.page_num >= self.total_page:
            html_str_list.append('<li class="disabled"><a href="#"><span aria-hidden="true">»</span></a></li>')
        else:
            html_str_list.append('<li><a href="{}?page={}"><span aria-hidden="true">»</span></a></li>'.format( self.url_prefix, self.page_num+1))
        # 加最后一页
        html_str_list.append('<li><a href="{}?page={}">尾页</a></li>'.format( self.url_prefix, self.total_page))

        page_html = "".join(html_str_list)
        return page_html

2.后端调用封装好的模块

def student(request):
    page_num = request.GET.get("page")
    total_count = models.Student.objects.all().count()

    # 调用封装好的类
    from utils.mypage import Page
    page_obj = Page(page_num, total_count, per_page=10, url_prefix="/student/", max_page=9, )

    ret = models.Student.objects.all()[page_obj.start:page_obj.end]  # 获取页面展示的数据

    page_html = page_obj.page_html()  # HTML代码
    return render(request, "student.html", {"students": ret, "page_html": page_html})

html代码和上面的一样

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: