批量操作数据、自定义分页器

批量操作数据

浏览器访问一个django路由 立刻创建10万条数据并展示到前端页面

1.常规批量插入数据

def index(request):     # 插入10000条数据     for i in range(10000):         models.Book.objects.create(title='第%s本书' % i)     book_queryset = models.Book.objects.all() 

2.使用orm提供的bulk_create方法批量插入数据(效率高 减少操作时间)

def index(request):     # 插入10000条数据     # for i in range(10000):     #     models.Book.objects.create(title='第%s本书' % i)     book_list = []     for i in range(10000):         book_obj = models.Book(title=f'第{i}本书')         book_list.append(book_obj)     # [models.Book(title=f'第{i}本书') for i in range(10000)]  # 可以使用列表生成式     models.Book.objects.bulk_create(book_list)  # 批量创建     # models.Book.objects.bulk_update()  # 批量创建     book_queryset = models.Book.objects.all()  # 查询数据     return render(request, 'bookList.html', locals()) 
涉及到大批量数据的创建 直接使用create可能会造成数据库崩溃     批量数据创建>>>:bulk_create()     批量数据修改>>>:bulk_update() 

前端页面展示数据

{% for book_obj in book_queryset %}     <p>{{ book_obj.title }}</p> {% endfor %} 

批量操作数据、自定义分页器

自定义分页器

1.针对上一小节批量插入的数据,我们在前端展示的时候发现一个很严重的问题,一页展示了索引的数据,数据量太大,查看不方便
2.针对数据量大但又需要全部展示给用户观看的情况下,我们统一做法都是做分页处理。很多网站都做了这样的操作

批量操作数据、自定义分页器

分页推导过程

当数据量比较大的时候 页面展示应该考虑分页 1.QuerySet切片操作 2.分页样式添加 3.页码展示 	如何根据总数据和每页展示的数据得出总页码    	divmod() 4.如何渲染出所有的页码标签 	前端模板语法不支持range 但是后端支持 我们可以在后端创建好html标签然后传递给html页面使用 5.如何限制住展示的页面标签个数 	页码推荐使用奇数位(对称美)  利用当前页前后固定位数来限制 6.首尾页码展示范围问题 """ 上述是分页器组件的推导流程 我们无需真正编写 	django自带一个分页器组件 但是不太好用 我们自己也写了一个 """ 

1.依靠索引切片

def ab_pl(request):    book_data = models.Book.objects.all()     # 计算总共数据条数     all_count = book_data.count()     # 2.自定义每页展示的数据条数     per_page_num = 10     all_page_num, more = divmod(all_count, per_page_num)     if more:         all_page_num += 1     # 后端生成页码标签     html_page = ''     for i in range(1, all_page_num):         html_page += '<li><a href="?page=%s">%s</a></li>' % (i, i)      # 1.获取前端想要展示的页码     current_page = request.GET.get('page', 1)  # 获取用户展示的page页 如果么有则默认展示1     try:         current_page = int(current_page)     except TypeError:         current_page = 1     # 3.定义出切片起始位置     start_num = (current_page - 1) * per_page_num     # 4.定义出切片终止位置     end_num = current_page * per_page_num     book_query = book_data[start_num:end_num]  # QuerySet [数据对象 数据对象]     return render(request, 'bookList.html', locals())  动态计算/解析出 起始位置 与 终止位置  # 每页展示10条 per_page_num = 10     页                    起始位置             终止位置   current_page            start_page          end_page     1                       0                   10      2                       10                  20      3                       20                  30        4                       30                  40      # 每页展示5条     per_page_num = 5     页                    起始位置             终止位置   current_page            start_page          end_page     1                        0                  5     2                        5                  10     3                        10                 15     4                        15                 20   计算出 起始位置 与 终止位置         0  = (1 - 1) * 5        start_page = (current_page - 1) * per_page_num          5  =  1 * 5 end_page = current_page * per_page_num 

批量操作数据、自定义分页器

2.通过代码动态计算出到底需要多少页

使用内置方法divmod

内置方法之divmod >>> divmod(100,10) (10, 0)  # 10页 >>> divmod(101,10) (10, 1)  # 11页 >>> divmod(99,10) (9, 9)  # 10页 # 余数只要不是0就需要在第一个数字上加一 

显示每页数据

book_data = models.Book.objects.all() # 计算总共数据条数 all_count = book_data.count() # 2.自定义每页展示的数据条数 per_page_num = 10 all_page_num, more = divmod(all_count, per_page_num) # 我们可以判断元祖的第二个数字是否为0从而确定到底需要多少页来展示数据 if more:     all_page_num += 1 # 后端生成页码标签 html_page = '' for i in range(1, all_page_num):     html_page += '<li><a href="?page=%s">%s</a></li>' % (i, i) 

利用start_page和end_page对总数据进行切片取值再传入前端页面

book_query = book_data[start_num:end_num]  # QuerySet [数据对象 数据对象]     return render(request, 'bookList.html', locals()) 

copy分页器的代码(bootstrap)

后端代码

def index(request):     book_data = models.Book.objects.all()     # 计算总共数据条数     all_count = book_data.count()     # 2.自定义每页展示的数据条数     per_page_num = 10     all_page_num, more = divmod(all_count, per_page_num)     if more:         all_page_num += 1     # 后端生成页码标签     html_page = ''     for i in range(1, all_page_num):         html_page += '<li><a href="?page=%s">%s</a></li>' % (i, i)      # 1.获取前端想要展示的页码     current_page = request.GET.get('page', 1)  # 获取用户展示的page页 如果么有则默认展示1     try:         current_page = int(current_page)     except TypeError:         current_page = 1     # 3.定义出切片起始位置     start_num = (current_page - 1) * per_page_num     # 4.定义出切片终止位置     end_num = current_page * per_page_num     book_query = book_data[start_num:end_num]  # QuerySet [数据对象 数据对象]     return render(request, 'bookList.html', locals()) 

前端页面

<div class="container">     <div class="row">         <div class="col-md-8 col-md-offset-2">             {% for book_obj in book_query %}                 <p class="text-center">{{ book_obj.title }}</p>             {% endfor %}             <nav aria-label="Page navigation " class="text-center">                 <ul class="pagination">                     <li>                         <a href="#" aria-label="Previous">                             <span aria-hidden="true">&laquo;</span>                         </a>                     </li>                     {{ html_page | safe }}                     <li>                         <a href="#" aria-label="Next">                             <span aria-hidden="true">&raquo;</span>                         </a>                     </li>                 </ul>             </nav>         </div>     </div> </div> 

批量操作数据、自定义分页器

限制展示页面标签个数

页码推荐使用奇数位(对称美) 利用当前页前后固定位数来限制
批量操作数据、自定义分页器

def index(request):     book_data = models.Book.objects.all()     # 计算总共数据条数     all_count = book_data.count()     # 2.自定义每页展示的数据条数     per_page_num = 10     all_page_num, more = divmod(all_count, per_page_num)     if more:         all_page_num += 1         # 1.获取前端想要展示的页码     current_page = request.GET.get('page', 1)  # 获取用户展示的page页 如果么有则默认展示1     try:         current_page = int(current_page)     except TypeError:         current_page = 1     # 后端生成页码标签     html_page = ''     xxx = current_page     # 一旦页码小于6的时候就叫他等于6,否则不做处理的话就会页面变为负数,出现报错     if current_page < 6:         xxx = 6     for i in range(xxx - 5, xxx + 6):         if current_page == i:             # 如果当前页面是展示的页面就添加一个active             html_page += '<li class="active"><a href="?page=%s">%s</a></li>' % (i, i)         else:             html_page += '<li><a href="?page=%s">%s</a></li>' % (i, i)     # 3.定义出切片起始位置     start_num = (current_page - 1) * per_page_num     # 4.定义出切片终止位置     end_num = current_page * per_page_num     book_query = book_data[start_num:end_num]  # QuerySet [数据对象 数据对象]     return render(request, 'bookList.html', locals()) 
<div class="container">     <div class="row">         <div class="col-md-8 col-md-offset-2">             {% for book_obj in book_query %}                 <p class="text-center">{{ book_obj.title }}</p>             {% endfor %}             <nav aria-label="Page navigation " class="text-center">                 <ul class="pagination">                     <li>                         <a href="#" aria-label="Previous">                             <span aria-hidden="true">&laquo;</span>                         </a>                     </li>                     {{ html_page |safe}}                     <li>                         <a href="#" aria-label="Next">                             <span aria-hidden="true">&raquo;</span>                         </a>                     </li>                 </ul>             </nav>         </div>     </div> </div> 

自定义分页器使用

点击查看代码
class Pagination(object):     def __init__(self,current_page,all_count,per_page_num=2,pager_count=11):         """         封装分页相关数据         :param current_page: 当前页         :param all_count:    数据库中的数据总条数         :param per_page_num: 每页显示的数据条数         :param pager_count:  最多显示的页码个数                  用法:         queryset = model.objects.all()         page_obj = Pagination(current_page,all_count)         page_data = queryset[page_obj.start:page_obj.end]         获取数据用page_data而不再使用原始的queryset         获取前端分页样式用page_obj.page_html         """         try:             current_page = int(current_page)         except Exception as e:             current_page = 1          if current_page <1:             current_page = 1          self.current_page = current_page          self.all_count = all_count         self.per_page_num = per_page_num           # 总页码         all_pager, tmp = divmod(all_count, per_page_num)         if tmp:             all_pager += 1         self.all_pager = all_pager          self.pager_count = pager_count         self.pager_count_half = int((pager_count - 1) / 2)      @property     def start(self):         return (self.current_page - 1) * self.per_page_num      @property     def end(self):         return self.current_page * self.per_page_num      def page_html(self):         # 如果总页码 < 11个:         if self.all_pager <= self.pager_count:             pager_start = 1             pager_end = self.all_pager + 1         # 总页码  > 11         else:             # 当前页如果<=页面上最多显示11/2个页码             if self.current_page <= self.pager_count_half:                 pager_start = 1                 pager_end = self.pager_count + 1              # 当前页大于5             else:                 # 页码翻到最后                 if (self.current_page + self.pager_count_half) > self.all_pager:                     pager_end = self.all_pager + 1                     pager_start = self.all_pager - self.pager_count + 1                 else:                     pager_start = self.current_page - self.pager_count_half                     pager_end = self.current_page + self.pager_count_half + 1          page_html_list = []         # 添加前面的nav和ul标签         page_html_list.append('''                     <nav aria-label='Page navigation>'                     <ul class='pagination'>                 ''')         first_page = '<li><a href="?page=%s">首页</a></li>' % (1)         page_html_list.append(first_page)          if self.current_page <= 1:             prev_page = '<li class="disabled"><a href="#">上一页</a></li>'         else:             prev_page = '<li><a href="?page=%s">上一页</a></li>' % (self.current_page - 1,)          page_html_list.append(prev_page)          for i in range(pager_start, pager_end):             if i == self.current_page:                 temp = '<li class="active"><a href="?page=%s">%s</a></li>' % (i, i,)             else:                 temp = '<li><a href="?page=%s">%s</a></li>' % (i, i,)             page_html_list.append(temp)          if self.current_page >= self.all_pager:             next_page = '<li class="disabled"><a href="#">下一页</a></li>'         else:             next_page = '<li><a href="?page=%s">下一页</a></li>' % (self.current_page + 1,)         page_html_list.append(next_page)          last_page = '<li><a href="?page=%s">尾页</a></li>' % (self.all_pager,)         page_html_list.append(last_page)         # 尾部添加标签         page_html_list.append('''                                            </nav>                                            </ul>                                        ''')         return ''.join(page_html_list)  

自定义分页器的拷贝及使用

1.当我们需要使用到非django内置的第三方功能或者组件代码的时候 我们一般情况下会创建一个名为utils文件夹 在该文件夹内对模块进行功能性划分 utils可以在每个应用下创建 具体结合实际情况  2.我们到了后期封装代码的时候 不再局限于函数 还是尽量朝面向对象去封装  3.我们自定义的分页器是基于bootstrap样式来的 所以你需要提前导入bootstrap 	bootstrap   版本  v3	 	jQuery		版本 v3 

最后封装好的版本使用

点击查看代码
""" utils可以建在项目下,也可以建在应用下! """ class Pagination(object):     def __init__(self, current_page, all_count, per_page_num=10, pager_count=11):         """         封装分页相关数据         :param current_page: 当前页         :param all_count:    数据库中的数据总条数         :param per_page_num: 每页显示的数据条数         :param pager_count:  最多显示的页码个数         """         try:  # 转换当前页             current_page = int(current_page)         except Exception as e:             current_page = 1         # 保证当前页被我们正常的获取到         if current_page < 1:             current_page = 1          # 对象赋值属性         self.current_page = current_page          self.all_count = all_count         self.per_page_num = per_page_num          # 总页码         all_pager, tmp = divmod(all_count, per_page_num)         if tmp:             all_pager += 1         self.all_pager = all_pager         # 赋值属性         self.pager_count = pager_count         self.pager_count_half = int((pager_count - 1) / 2)      # 方法伪装成数据 对象调的时候不需要加括号 也可以正常访问到     @property     def start(self):         return (self.current_page - 1) * self.per_page_num      @property     def end(self):         return self.current_page * self.per_page_num      def page_html(self):  # 生成分页器所有编码         # 如果总页码 < 11个:         if self.all_pager <= self.pager_count:             pager_start = 1             pager_end = self.all_pager + 1         # 总页码  > 11         else:             # 当前页如果<=页面上最多显示11/2个页码             if self.current_page <= self.pager_count_half:                 pager_start = 1                 pager_end = self.pager_count + 1              # 当前页大于5             else:                 # 页码翻到最后                 if (self.current_page + self.pager_count_half) > self.all_pager:                     pager_end = self.all_pager + 1                     pager_start = self.all_pager - self.pager_count + 1                 else:                     pager_start = self.current_page - self.pager_count_half                     pager_end = self.current_page + self.pager_count_half + 1          page_html_list = []         # 添加前面的nav和ul标签         page_html_list.append('''                     <nav aria-label='Page navigation>'                     <ul class='pagination'>                 ''')         first_page = '<li><a href="?page=%s">首页</a></li>' % (1)         page_html_list.append(first_page)          if self.current_page <= 1:             prev_page = '<li class="disabled"><a href="#">上一页</a></li>'         else:             prev_page = '<li><a href="?page=%s">上一页</a></li>' % (self.current_page - 1,)          page_html_list.append(prev_page)          for i in range(pager_start, pager_end):  # 高亮显示             if i == self.current_page:                 temp = '<li class="active"><a href="?page=%s">%s</a></li>' % (i, i,)             else:                 temp = '<li><a href="?page=%s">%s</a></li>' % (i, i,)             page_html_list.append(temp)          if self.current_page >= self.all_pager:             next_page = '<li class="disabled"><a href="#">下一页</a></li>'         else:             next_page = '<li><a href="?page=%s">下一页</a></li>' % (self.current_page + 1,)         page_html_list.append(next_page)          last_page = '<li><a href="?page=%s">尾页</a></li>' % (self.all_pager,)         page_html_list.append(last_page)         # 尾部添加标签         page_html_list.append('''                                            </nav>                                            </ul>                                        ''')         return ''.join(page_html_list)   

后端

# 导入utils文件 from utils.mypage import Pagination  def ab_pl(request):     # 获取页面展示多少数据     book_queryset = models.Book.objects.all()     # 当前页     current_page = request.GET.get('page', 1)     # 总条数     all_count = book_queryset.count()     # 1.传值生成对象     page_obj = Pagination(current_page=current_page, all_count=all_count)     # 2.直接对总数据进行切片操作     page_queryset = book_queryset[page_obj.start:page_obj.end]  # 计算出起始位置与终止位置     # 3.将page_queryset传递到页面 替换之前的book_queryset      return render(request,'ab_pl.html',locals()) 

前端

<!DOCTYPE html> <html lang="en"> <head>     <meta charset="UTF-8">     <title>Title</title>     <!--bootstrap引入 CSS CDN-->     <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">     <!--jQuery引入 CDN-->     <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.4.1/jquery.min.js"></script>     <!--Bootstrap引入 Js CDN-->     <script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script> </head> <body>  {#循环数据#} {% for book_obj in page_queryset %}     <p>{{ book_obj.title }}</p> {% endfor %}  {# 利用自定义分页器直接显示分页器样式 #} {{ page_obj.page_html|safe }}  </body> </html> 

发表评论

评论已关闭。

相关文章

当前内容话题