Django(分页)

day71

参考:http://www.cnblogs.com/liwenzhou/p/8660826.html#autoid-4-1-0

 

day71

参考:http://www.cnblogs.com/liwenzhou/p/8343243.html#autoid-0-4-5

分页

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

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

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

准备工作

我们使用脚本批量创建一些测试数据(将下面的代码保存到bulk_create.py文件中放到Django项目的根目录,直接执行即可。):

 1 import os
 2 
 3 if __name__ == "__main__":
 4     os.environ.setdefault("DJANGO_SETTINGS_MODULE", "about_orm.settings")
 5 
 6     import django
 7     django.setup()
 8 
 9     from app01 import models
10     bulk_obj = (models.Publisher(name='沙河第{}出版社'.format(i)) for i in range(300))
11     models.Publisher.objects.bulk_create(bulk_obj)

不分页

 

 

分页代码分析:

数据格式:

显示内容部分:

导航条部分:

导航条样式

 

完整代码:

books.html

 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <title>书籍列表</title>
 6     <link rel="stylesheet" href="/static/bootstrap/css/bootstrap.css">
 7 </head>
 8 <body>
 9 <div class="container">
10     <table class="table table-bordered">
11         <thread>
12             <tr>
13                 <th>序号</th>
14                 <th>id</th>
15                 <th>书名</th>
16             </tr>
17         </thread>
18         <tbody>
19         {% for book in books %}
20             <tr>
21             <td>{{ forloop.counter }}</td>
22             <td>{{ book.id }}</td>
23             <td>{{ book.title }}</td>
24             </tr>
25         {% endfor %}
26 
27         </tbody>
28     </table>
29     <nav aria-label="Page navigation">
30         <ul class="pagination">
31             <li>
32 
33 
34                 <li>
35                     {{ page_html|safe }}
36                 </li>
37 
38             </li>
39         </ul>
40     </nav>
41 </div>
42 
43 </body>
44 </html>

views.py

 1 def books(request):
 2     # 从url取参数
 3     page_num = request.GET.get("page")  # url中拿到
 4     page_num = int(page_num)
 5 
 6     # 以上决定的是页面显示的内容
 7     # 一下决定导航条的内容
 8     # 每一页显示多少条数据
 9     per_page = 10
10     # 总数据条数
11     total_count = models.Book.objects.all().count()
12     # 总共需要多少页码显示
13     total_page, m = divmod(total_count, per_page)  # 共total_count条数据, 每页per_page条显示
14     if m:  # 有值 需加1
15         total_page += 1  # 共需total_count+=1页显示
16     try:
17         page_num = int(page_num)
18         # 如果页数超过最大页码数,返回最后一页
19         if page_num > total_page:
20             page_num = total_page
21         if page_num < 1:
22             page_num = 1
23     except Exception as e:
24         page_num = 1
25 
26     # 定义两个变量
27     data_start = (page_num - 1) * 10
28     data_end = page_num * 10
29     all_book = models.Book.objects.all()[data_start:data_end]
30 
31     # 页面上总共展示多少页码
32     max_page = 11
33     if total_page < max_page: # 总页数过小,小于设定
34         max_page = total_page
35     half_max_page = max_page // 2
36     # 页面上展示的页码从哪开始
37     page_start = page_num - half_max_page
38     # 到哪儿结束
39     page_end = page_num + half_max_page
40     # 如果起始值小于等于1
41     if page_start <= 1:
42         page_start = 1
43         page_end = max_page
44     # 如果当前页加一半比总页码数还大
45     if page_end >= total_page:
46         page_end = total_page
47         page_start = total_page - max_page + 1   # 导航条显示数量必须相同
48 
49 
50 
51     # 自己拼接分页的HTML代码
52     html_str_list = []
53     # 加上第一页
54     html_str_list.append('<li><a href="/books/?page=1">首页</a></li>')
55     # 加上一个上一页的标签                                                                     只要中间页往前移就整体往前移一页
56     #html_str_list.append('<li><a href="/books/?page={}"><span aria-hidden="true">&laquo;</span></a></li>'.format(page_num-1))
57     if page_num == 1: # 如果已经是第一页了就不在跳转 #
58         html_str_list.append(
59             '<li class="disabled"><a href="#"><span aria-hidden="true">&laquo;</span></a></li>')
60     else:
61         html_str_list.append(
62             '<li><a href="/books/?page={}"><span aria-hidden="true">&laquo;</span></a></li>'.format(page_num - 1))
63     for i in range(page_start, page_end+1):
64         # # 跳转内容带 page 巧妙! page决定了显示哪些内容在页面上
65         if i == page_num:
66                         # 当前页高亮
67             tmp = '<li class="active"><a href="/books/?page={0}">{0}</a></li>'.format(i)
68         else:
69             tmp = '<li><a href="/books/?page={0}">{0}</a></li>'.format(i)
70         html_str_list.append(tmp)
71     # 加上一个下一页的标签                               只要中间页往前移就整体往前移一页
72     if page_num == total_page: # 如果已经是最后一页了就不在跳转 #
73         html_str_list.append(
74             '<li class="disabled"><a href="#"><span aria-hidden="true">&raquo;</span></a></li>')
75     else:
76         html_str_list.append(
77             '<li><a href="/books/?page={}"><span aria-hidden="true">&raquo;</span></a></li>'.format(page_num + 1))
78     # 加上尾页
79     html_str_list.append('<li><a href="/books/?page={}">尾页</a></li>'.format(total_page))
80     page_html = "".join(html_str_list)
81     return render(request, "books.html", {"books": all_book, "page_html": page_html})

 

将以上内容封装成通用模块

@property

以下为完整程序:

views.py

def depts(request):
    # 从URL取参数
    page_num = request.GET.get("page")
    print(page_num, type(page_num))
    # 总数据是多少
    total_count = models.Dept.objects.all().count()
    from utils.mypage import Page # 调用自己写的模块
    # 创建对象
    page_obj = Page(page_num, total_count, per_page=10, url_prefix="/depts/", max_page=11, )

    ret = models.Dept.objects.all()[page_obj.start:page_obj.end]  # 调用该对象中的方法
    print(ret)
    # 使用对象方法
    page_html = page_obj.page_html()
    return render(request, "dept.html", {"depts": ret, "page_html": page_html})

mypage.py

 1 class Page():
 2                                              #  路径
 3     def __init__(self, page_num, total_count, url_prefix, per_page=10, max_page=11):
 4         """
 5 
 6         :param page_num: 当前页码数
 7         :param total_count: 数据总数
 8         :param url_prefix: a标签href的前缀
 9         :param per_page: 每页显示多少条数据
10         :param max_page: 页面上最多显示几个页码
11         """
12         self.url_prefix = url_prefix
13         self.max_page = max_page
14         # 每一页显示多少条数据
15         # 总共需要多少页码来展示
16         total_page, m = divmod(total_count, per_page)
17         if m:
18             total_page += 1
19         self.total_page = total_page
20 
21         try:
22             page_num = int(page_num)
23             # 如果输入的页码数超过了最大的页码数,默认返回最后一页
24             if page_num > total_page:
25                 page_num = total_page
26         except Exception as e:
27             # 当输入的页码不是正经数字的时候 默认返回第一页的数据
28             page_num = 1
29         self.page_num = page_num
30 
31         # 定义两个变量保存数据从哪儿取到哪儿    决定显示的数据
32         self.data_start = (page_num - 1) * 10
33         self.data_end = page_num * 10
34 
35         # 页面上总共展示多少页码
36         if total_page < self.max_page:
37             self.max_page = total_page
38 
39         half_max_page = self.max_page // 2
40         # 页面上展示的页码从哪儿开始
41         page_start = page_num - half_max_page
42         # 页面上展示的页码到哪儿结束
43         page_end = page_num + half_max_page
44         # 如果当前页减一半 比1还小
45         if page_start <= 1:
46             page_start = 1
47             page_end = self.max_page
48         # 如果 当前页 加 一半 比总页码数还大
49         if page_end >= total_page:
50             page_end = total_page
51             page_start = total_page - self.max_page + 1
52         self.page_start = page_start
53         self.page_end = page_end
54 
55     @property  # page_obj.start 表示返回数据本身
56     def start(self):   # 这部分是显示内容的部分,并不是导航条的部分    显示数据的开始与结束
57         return self.data_start
58 
59     @property
60     def end(self):
61         return self.data_end
62 
63 
64     def page_html(self):
65         # 自己拼接分页的HTML代码
66         html_str_list = []
67         # 加上第一页
68         html_str_list.append('<li><a href="{}?page=1">首页</a></li>'.format( self.url_prefix))
69 
70         # 判断一下 如果是第一页,就没有上一页
71         if self.page_num <= 1:
72             html_str_list.append('<li class="disabled"><a href="#"><span aria-hidden="true">&laquo;</span></a></li>'.format(self.page_num-1))
73         else:
74             # 加一个上一页的标签
75             html_str_list.append('<li><a href="{}?page={}"><span aria-hidden="true">&laquo;</span></a></li>'.format( self.url_prefix, self.page_num-1))
76 
77         for i in range(self.page_start, self.page_end+1):
78             # 如果是当前页就加一个active样式类
79             if i == self.page_num:                                              #路径和页码
80                 tmp = '<li class="active"><a href="{0}?page={1}">{1}</a></li>'.format(self.url_prefix, i)
81             else:
82                 tmp = '<li><a href="{0}?page={1}">{1}</a></li>'.format( self.url_prefix, i)
83 
84             html_str_list.append(tmp)
85 
86         # 加一个下一页的按钮
87         # 判断,如果是最后一页,就没有下一页
88         if self.page_num >= self.total_page:
89             html_str_list.append('<li class="disabled"><a href="#"><span aria-hidden="true">&raquo;</span></a></li>')
90         else:
91             html_str_list.append('<li><a href="{}?page={}"><span aria-hidden="true">&raquo;</span></a></li>'.format( self.url_prefix, self.page_num+1))
92         # 加最后一页
93         html_str_list.append('<li><a href="{}?page={}">尾页</a></li>'.format( self.url_prefix, self.total_page))
94 
95         page_html = "".join(html_str_list)
96         return page_html

含三个方法,前两个获得显示数据的起始与结束,第三个获得导航条需要显示的内容。

dept.html

 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <title>部门列表</title>
 6     <link rel="stylesheet" href="/static/bootstrap/css/bootstrap.min.css">
 7 </head>
 8 <body>
 9 
10 <div class="container">
11     <table class="table table-bordered">
12       <thead>
13         <tr>
14             <th>序号</th>
15             <th>id</th>
16             <th>部门名</th>
17         </tr>
18       </thead>
19         <tbody>
20         {% for dept in depts %}
21             <tr>
22             <td>{{ forloop.counter }}</td>
23             <td>{{ dept.id }}</td>
24             <td>{{ dept.name }}</td>
25             </tr>
26         {% endfor %}
27 
28         </tbody>
29 </table>
30 <nav aria-label="Page navigation">
31   <ul class="pagination">
32         {{ page_html|safe }}
33   </ul>
34 </nav>
35 </div>
36 </body>
37 </html>

 

效果:

 

posted on 2019-03-11 21:35  嘟嘟嘟啦  阅读(187)  评论(0编辑  收藏  举报

导航