栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Python

Django 批量操作数据以及分页器

Python 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Django 批量操作数据以及分页器

文章目录
    • 1. 批量操作数据
      • bulk_create 方法
    • 2. 分页器推导
    • 分页器最终版本

1. 批量操作数据

在操作大批数据的时候,例如在数据库表中插入大批量的记录时,可以使用该方法减少运行时间,首先可以尝试直接插入多条数据,如下所示

urls.py

from django.conf.urls import url
from app01 import views

urlpatterns = [
	url(r'^get_book/',views.get_book)
]

models.py

from django.db import models

class Book(models.Model):
	title = models.CharField(max_length=64)
  

views.py

from django.shortcuts import render, HttpResponse, redirect
from app01 import models

def get_book(request):
  # for循环插入1000条数据
	for i in range(1000):
		models.Book.objects.create(name='第%s本书'%i)
  # 将插入的数据再查询出来
	book_queryset = models.Book.objcets.all()
	return render(request,'get_book.html',locals())  # 将查询出来的数据传递给html页面
	

template/get_book.html




    
    Title
    
    {% load static %}
    
    
    
    


{#对结果集进行for循环#} {% for book in book_queryset %} {#循环展示书名#}

{{ book.title }}

{% endfor %}

在插入大批量的时候,浏览器会等待很久,这是因为后端在不停的操作数据库,所以看起来想卡了,直接操作大批量的数据效率并不高,我们可以使用 bulk_create方法提升效率

bulk_create 方法

在 views.py 中使用该方法即可

from django.shortcuts import render, HttpResponse, redirect
from app01 import models

def get_book(request):
    '''批量插入'''
    book_list = []
    for i in range(100000):
        # 先用类产生一个对象
        source_book_obj = models.Books(title=f'第{i}本书')
        # 将对象追加到列表中
        book_list.append(source_book_obj)
    models.Books.objects.bulk_create(book_list)  # 批量插入
    book_queryset = models.Books.objects.all()
    return render(request,'many_data.html',locals())
    
2. 分页器推导

在前面批量插入了多条数据,但是肯定不能在页面上同时展示这么多数据,就需要使用分页器的功能了。

1. 首先分页,首先肯定要有展示数据的条数、开始展示的位置、结束展示的位置、分页器页码的数量等参数。
2. 我们可以在路由后携带类似于 https://blog.csdn.net/m0_58987515/article/details/124890894?page=1 的数据来表示当前页码,并对结果集进行切片让其展示固定位置数据。
	
	class sorter(View):
	    def get(self, request):
	    	# 获取请求中的page值
	        page_num = request.GET.get('page')
	        try:
	        	# 将其转为数字类型
	            page_num = int(page_num)
	        except Exception:
	        	# 如果不存在将其转为1
	            page_num = 1
	        # 对结果集进行切片操作
	        book_queryset = models.Books.objects.all()[20:30]

        
3. 虽然可以展示出指定位置的数字,但是此时是写死的,我们需要动态的获得指定的位置,在此我们可以看下页码参数
(page_num)、开始的位置(start_num)和结束的位置(stop_num)以及展示的条数(show_num)之间的关系,如下表所示
页码展示条数页码结果集开始位置结果集结束位置
5105
52510
531015
页码展示条数页码结果集开始位置结果集结束位置
101010
1021020
1032030
4. 我们可以发现,结果集开始的位置是页码展示条数与页码减一的乘积,而结果集结束的位置是页码展示条数和页码的乘积
关系如下所示,此时就可以动态的切片结果集了,如下所示

	# 关系展示
	start_num = show_num * (page_num - 1)
	stop_num = show_num * page_num 
 
 	# 动态切割结果集
    class sorter(View):
		def get(self, request):
			page_num = request.GET.get('page')
		    try:
		    	page_num = int(page_num)
	        except Exception:
	            page_num = 1
	        # 设置最大展示的条数
	        show_num = 10
	        # 动态结果集起始的位置
	        start_num = (page_num-1) * show_num
	        # 动态结果集结束的位置
	        stop_num = page_num * show_num
	        # 对结果集动态切片
	        book_queryset = models.Books.objects.all()[start_num:stop_num]
	        return render(request, 'book.html', locals())
    
        
5. 接下来就是引入分页器的样式了,这里使用的是 Bootstrap 框架提供的分页器,修改其链接,如下

	
{% for foo in book_queryset %}

{{ foo.name }}

{% endfor %}
6. 虽然实现了简易分页,但是其跳转的页码是写死的,我们可以把它放在后端编写,首先要了解页码数量和数据条数之间的
关系,如下表所示,就算数据条数只多出一条,也要一个页码储存。在后端使用的方法是 'divmod', divmod() 函数把除
数和余数运算结果结合起来,返回一个包含商和余数的元组,如下示意

	# divmod 内置方法使用示意
	>>> divmod(100,10)
	(10, 0)  # 10页
	>>> divmod(101,10)
	(10, 1)  # 11页
	>>> divmod(99,10)
	(9, 9)  # 10页
	# 余数只要不是0就需要在第一个数字上加一
	
数据条数页码最大展示条数页码数
991010
1001010
1011011
7. 在后端编写html代码发生到前端,如下所示

'views.py文件'
	class sorter(View):
	    def get(self, request):
	        page_num = request.GET.get('page')
	        # 获取当前结果集
	        data_queryset = models.Books.objects.all()
	        try:
	            page_num = int(page_num)
	        except Exception:
	            page_num = 1
	        show_num = 10
	        start_num = (page_num - 1) * show_num
	        stop_num = page_num * show_num
	        # 获取结果集数据的个数
	        all_count = data_queryset.count()
	        # 使用divmod方法
	        more, others = divmod(all_count, page_num)
	        # 如果有余数,页码数量加1
	        if others:
	            more += 1
	        # 创建空字符串用于接收html代码
	        html = ''
	        # for循环,循环生成html代码
	        for i in range(1, more+1):
	        	# 添加到空字符串中
	            html += f'
  • {i}">{i}
  • ' # 切片 book_queryset = data_queryset[start_num:stop_num] return render(request, 'book.html', locals()) 'book.html文件'
    {% for foo in book_queryset %}

    {{ foo.name }}

    {% endfor %}
    8. 页码已经有了功能,但是现在是一次性将页码都展示,我们需要对其最终优化,如下
    
    	class sorter(View):
    	    def get(self, request):
    	    	# 获取当前页码page值
    	        page_num = request.GET.get('page')
    	        # 获取结果集
    	        data_queryset = models.Books.objects.all()
    	        try:
    	        	# 将其转为数字类型
    	            page_num = int(page_num)
    	        except Exception:
    	        	# 异常时赋值为1
    	            page_num = 1
    	        # 定义一个页码展示的最大条数
    	        show_num = 10
    	        # 动态获取结果集切片开始的位置
    	        start_num = (page_num - 1) * show_num
    	        # 动态获取结果集切片结束的位置
    	        stop_num = page_num * show_num
    	        # 获取结果集数据的总条数
    	        all_count = data_queryset.count()
    	        # 获取整除数和余数,整除的数量就是页码的总数量,余数是多出来的数据条数
    	        more, others = divmod(all_count, show_num)
    	        if others:
    	        	# 如果有余数,需要在添加一页存放数据
    	            more += 1
    	        # 创建一个变量指向当前页码
    	        more_page = page_num
    	        
    	        # 若当前页码小于等于6,range(1, 12)。
    	        if more_page < 6:
    	            more_page = 6
    	        # 假设最大页码数是27,若当前页码大于22时,例如为23,则range(17,28)。页码为25也为range(17,28)
    	        if more_page > (more - 5):
    	            more_page = more - 5
    	        # 创建空字符串
    	        html = ''
    	        # 这里设定只展示11个页码,不小于6和不大于more - 5的页码按照其所在位置展示前后5个页码
    	        for i in range(more_page - 5, more_page + 6):
    	        	# 将当前页码添加高亮
    	            if i == page_num:
    	                html += f'
  • {i}">{i}
  • ' else: html += f'
  • {i}">{i}
  • ' # 动态切片结果集 book_queryset = data_queryset[start_num:stop_num] return render(request, 'book.html', locals()) 到这里简单的分页器功能就实现了,实际使用可以使用下面的模板
    分页器最终版本
    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:  最多显示的页码个数
            """
            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('''
                        
                                               
                                           ''')
            return ''.join(page_html_list)
    
    
    

    最终版本使用

    由于分页器会多次使用,我们可以创建一个utils文件夹用于存放分页器,将上面的类放到utils文件夹下的py文件中
    

    后端

    def get_book(request):
    	# 产生结果集对象
    	book_queryset = models.Book.objects.all()
    	# 获取page值
    	current_page = request.GET.get("page",1)
    	# 统计结果集个数
    	all_count = book_queryset.count()
    	# 实例化类,其中 page值、结果集个数是必传的参数,其他参数有设置默认值
    	page_obj = Pagination(current_page=current_page,all_count=all_count,per_page_num=10)
    	# 动态切片结果集
    	page_queryset = book_queryset[page_obj.start:page_obj.end]
    	return render(request,'book.html',locals())
    	
    

    前端

    {% for book in page_queryset %}

    {{ book.title }}

    {% endfor %} {{ page_obj.page_html|safe }}
    转载请注明:文章转载自 www.mshxw.com
    本文地址:https://www.mshxw.com/it/923687.html
    我们一直用心在做
    关于我们 文章归档 网站地图 联系我们

    版权所有 (c)2021-2022 MSHXW.COM

    ICP备案号:晋ICP备2021003244-6号