Django批量插入数据及分页器

news2024/11/16 23:42:23

文章目录

  • 一、批量插入数据
  • 二、分页
    • 1.分页器的思路
    • 2.用一个案例试试
    • 3.自定义分页器

一、批量插入数据

当我们需要大批量创建数据的时候,如果一条一条的去创建或许需要猴年马月 我们可以先试一试for循环试试

我们首先建立一个模型类来创建一个表

models.py;建议连接到MySQL数据库下进行实验

	class Book(models.Model):
    	name = models.CharField(max_length=32)

	'记得创建好模型类后,执行数据库迁移命令:makemigrations、migrate'

配置路由文件urls.py

	from django.conf.urls import url
	from django.contrib import admin
	from app import views
	urlpatterns = [
	    url(r'^admin/', admin.site.urls),
	    url(r'^data/', views.data),
	]
	'html代码'
	<div class="col-md-8 col-md-offset-2">
	    {% for book_obj in book_query %}
	    	 <p class="text-center" style="font-size:20px;">{{ book_obj.name }}</p>
	    {% endfor %}
	</div>

	'views.py'
	from app import models
	def data(request):
	    for i in range(10000):
	        models.Book.objects.create(name=f"第{i}本书")
	        
	    book_query = models.Book.objects.all()
	
	    return render(request,'data.html',locals())

	'''
    浏览器访问一个django路由,立刻创建1万条数据并展示到前端页面
    涉及到大批量数据的创建,直接使用create可能会造成数据库崩溃
    所以django就有一个专门来创建的参数就是 dulk_create还有dulk_update 效率极高
    '''

从最后批量插入数据的结果来看,效率太慢了。原因就是每一次插入一条数据时,都需要和数据库做链接,因此创建效率就特别慢。

所以我们就用到了django专门用来批量创建数据的参数dulk_create

	from app import models
	def data(request):
	    book_list = []
	    for i in range(10000):
	        book_obj = models.Book(name=f"第{i}本书")
	        book_list.append(book_obj)
	        
	    '''上述代码可以简化为一行'''
	    [models.Book(name=f"第{i}本书") for i in range(10000)]
	
	    models.Book.objects.bulk_create(book_list)  # 批量创建
	    # models.Book.objects.bulk_update(book_list)  # 批量更新
	    book_query = models.Book.objects.all()
	
	    return render(request,'data.html',locals())

最终结果:
在这里插入图片描述

从浏览器展示中可以看到,使用了bulk_create批量创建插入数据时,极快的创建完成后并在同一个页面展示出来了。但是这样展示出来的效果不够美观,所以我们需要把展示的数据进行分页展示


二、分页

这里我们将利用Django提供给我们的一个分页模块来帮助我们的页面达到一个分页的效果

1.分页器的思路

1.get请求也是可以携带参数的,所以我们在朝后端发送查看数据的同时可以携带一个参数告诉后端我们想看第几页的数据

	current_page = request.GET.get('page',1)  # 获取用户想访问的页码,如果没有,默认展示第一页
    try:  # 由于后端接收到的前端数据是字符串类型所以我们这里做类型转换处理加异常捕捉
        current_page = int(current_page)
    except Exception as f:
        current_page = 1
    # 还需要定义页面到底展示几条数据
    per_page_num = 10  # 一页展示10条数据

    # 需要对总数据进行切片操作,需要确定切片起始位置和终止位置
    start_page = (current_page-1)*per_page_num
    end_page = current_page*per_page_num

    '''
    下面需要研究current_page、per_page_num、start_page、end_page四个参数之间的数据关系
    per_page_num = 10
    current_page            start_page          end_page
        1                       0                  10
        2                       10                 20
        3                       20                 30  
        4                       30                 40
     
        
    per_page_num = 5
    current_page            start_page          end_page
        1                       0                  5
        2                       5                  10
        3                       10                 15  
        4                       15                 20
    
    可以很明显的看出规律
    start_page = (current_page-1)*per_page_num
    end_page = current_page*per_page_num
    '''

2.数据总页面获取

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

	总共需要多少页数
	info_queryset = models.UserInfo.objects.all()
    all_count = info_queryset.count()  # 数据总条数
    all_pager,more = divmod(all_count,per_page_num)
    if more:  # 有余数则总页数加一
        all_pager += 1

3.利用start_page和end_page对总数据进行切片取值再传入前端页面就能够实现分页展示

	后端
	info_list = models.UesrInfo.objects.all()[start_page:end_page]
	return render(request,'info.html',locals())

	前端
	{% for info in info_list %}
		<p>{{ info.name }}</p>
	{% endfor %}

4.由于模版语法没有range功能,但是我们需要循环产生很多分页标签,所以考虑后端生成传递给前端页面
后端

	html_srt = ''
	xxx = current_page
	if xxx<6:
		xxx = 6
	for i in range(xxx - 5,xxx+6)
		if current_page == i:
			html_str += '<li class="active"> <a href="?page=%s">%s</a></li>' %(i,i)
		else:
			html_str += '<li>href="?page=%s">%s</a></li>' % (i,i)

前端

	{{ html_str }}
	分页器主要是处理逻辑,代码最后很简单
	推导流程:
		1.queryset支持切片操作(正数)
		2.分页样式添加
		3.页码展示
			如果根据总数据和每页展示的数据得出总页码
			divmod()
		4.如何渲染出所有的页码标签
			前端模版语法不支持range 但是后端支持,我们可以在后端创建好html标签然后传递给html页面使用
		5.如何限制住展示的页面标签个数
			页码推荐使用奇数位(对称美),利用当前页前后固定位置来限制
		6.首尾页码展示范围问题
		
		上述是分页器组件的推导流程,我们无需真正编写
			django自带一个分页器组件,但是不是很好用,所以我们也可以自己自定义一个分页器

2.用一个案例试试

实验环境搭建
我们首先建立一个模型类来存储数据,因为要实现分页需要一定的数据量。

models.py;建议连接到MySQL数据库下进行实验

	class UserInfo(models.Model):
	    name = models.CharField(max_length=32)
	    age = models.CharField(max_length=32)
	    address = models.CharField(max_length=32)

	'记得创建好模型类后,执行数据库迁移命令:makemigrations、migrate'

配置路由文件urls.py

	from django.conf.urls import url
	from django.contrib import admin
	from app import views
	urlpatterns = [
	    url(r'^admin/', admin.site.urls),
	    url(r'^info/', views.info),
	]

tests.py 制作我们待会进行分页的数据,并将其写入数据库内

import os

if __name__ == "__main__":
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "nine.settings")
    import django
    django.setup()
    from app import models

    from faker import Faker  # 生成加的数据
    import random  # 用来创建随机年龄

    obj_list = []

    for i in range(300):  # 制作300条虚拟数据
        fake = Faker(locale='zh-CN')  # 选择地区

        name = fake.name()  # 生成随机名称
        age = random.randint(18,55)  # 生成随机年龄
        address = fake.address()  # 生成随机地址

        info_obj = models.UserInfo(name=name,age=age,address=address)  # 生成一个个用户对象

        obj_list.append(info_obj)

    models.UserInfo.objects.bulk_create(obj_list)  # 将一个个对象写入数据库内保存,一个对象对应一条记录

这里用到了一个Python第三方模块faker,主要是生成各种各样的伪数据。具体使用自行搜索引擎查找。

views.py:先简单的搭建出模型,在web能看到数据效果

	def info(request):
	    info_list = models.UserInfo.objects.all()  # 获取所有的数据
	    all_count = info_list.count()  # 通过计数获取有多少条数据
	    per_page_num = 10  # 自定义每一页展示的数据条数,这个时候就可以动态计算了
	    all_page_num,more = divmod(all_count,per_page_num)  # divmod计算需要多少页来展示
	    if more:
	        all_page_num += 1  # 这样就获取到了所有的页码的数量
	    current_page = request.GET.get('page',1) #获取用户指定的page,如果没有则默认展示第一页
	    try:
	        current_page = int(current_page)  # 因为返回给前端的是字符串要转换成整型
	    except ValueError:  # 抛出异常类型错误
	        current_page = 1
	
	    html_str = ''
	    xxx = current_page
	    if current_page < 6: # 一用户访问的页码小于6就等于6
	        xxx = 6
	
	    for i in range(xxx-5,xxx+6):
	        if current_page == i:
	            html_str += '<li class="active"><a href="?page=%s">%s</a></li>' % (i,i)
	        else:
	            html_str += '<li><a href="?page=%s">%s</a></li>' % (i,i)
	
	    start_page = (current_page-1)*per_page_num  # 定义出切片的起始位置
	    end_page = current_page*per_page_num  # 定义出切片的终止位置
	
	    info_query = models.UserInfo.objects.all()[start_page:end_page]
	    '''
	    all返回的是QuerySet,可以看成列表套对象,也就是说支持索引取值
	    现在的问题总可能让客户用源码修改页数吧?
	    '''
	    return render(request, 'info.html', locals())

info.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
    <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
    <script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>
</head>
<body>
<div class="container">
    <div class="row">
        <div class="col-md-8 col-md-offset-2">
            <table class="table table-striped">
                <thead>
                <tr>
                    <th class="text-center">ID</th>
                    <th class="text-center">姓名</th>
                    <th class="text-center">年龄</th>
                    <th class="text-center">住址</th>
                </tr>
                </thead>

                <tbody>
                {% for info in info_query %}
                    <tr class="text-center">
                        <td>{{ info.id }}</td>
                        <td>{{ info.name }}</td>
                        <td>{{ info.age }}</td>
                        <td>{{ info.address }}</td>
                    </tr>
                {% endfor %}
                </tbody>
            </table>

        </div>

        <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_str | safe }}
                <li>
                    <a href="#" aria-label="Next">
                        <span aria-hidden="true">&raquo;</span>
                    </a>
                </li>
            </ul>
        </nav>
    </div>
</div>
</body>
</html>

最终效果:
在这里插入图片描述


3.自定义分页器

是我们自己写好的分页器代码

一般是存在应用层.utils.mypage文件下的,我们需要的时候导入就行

	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('''
	                    <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)

自定义分页器的使用

	django自带分页器模块但是使用起来很麻烦 所以我们自己封装了一个

	只需要掌握使用方式即可
	后端
	def info(request):
	    info_list = models.UserInfo.objects.all()
	    from app.utils.my_page import Pagination  # 导入
	    current_page = request.GET.get('page') # 获取当前页
	    page_obj = Pagination(current_page=current_page,all_count=info_list.count(),per_page_num=10)  # 生成对象
	    info_query = info_list[page_obj.start:page_obj.end] # 切片
	    html = page_obj.page_html
	
	    return render(request,'info.html',locals())

前端

	<div class="container">
	    <div class="row">
	        <div class="col-md-8 col-md-offset-2">
	            <table class="table table-striped">
	                <thead>
	                <tr>
	                    <th class="text-center">ID</th>
	                    <th class="text-center">姓名</th>
	                    <th class="text-center">年龄</th>
	                    <th class="text-center">住址</th>
	                </tr>
	                </thead>
	
	                <tbody>
	                {% for info in info_query %}
	                    <tr class="text-center">
	                        <td>{{ info.id }}</td>
	                        <td>{{ info.name }}</td>
	                        <td>{{ info.age }}</td>
	                        <td>{{ info.address }}</td>
	                    </tr>
	                {% endfor %}
	                </tbody>
	            </table>
	         {{ html | safe }}
	        </div>
	    </div>
    </div>

最终结果:
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1235492.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【图像分类】【深度学习】【Pytorch版本】Inception-ResNet模型算法详解

【图像分类】【深度学习】【Pytorch版本】Inception-ResNet模型算法详解 文章目录 【图像分类】【深度学习】【Pytorch版本】Inception-ResNet模型算法详解前言Inception-ResNet讲解Inception-ResNet-V1Inception-ResNet-V2残差模块的缩放(Scaling of the Residuals)Inception-…

3.基于多能互补的热电联供微网优化运行复现(matlab代码)

0.代码链接 基于多能互补的热电联供微电网/综合能源系统优化运行&#xff08;Matlab程序Yalmip&#xff0b;Cplex求解&#xff09;_工业综合能源系统资源-CSDN文库 2. 主要内容&#xff1a;代码主要做的是多能互补的热电联供型微网优化运行模型&#xff0c;在需求侧对负荷类型…

视频集中存储EasyCVR平台使用海康SDK,播放出现串流情况是什么原因?

视频监控平台EasyCVR拓展性强&#xff0c;视频能力丰富&#xff0c;具体可实现视频监控直播、视频轮播、视频录像、云存储、回放与检索、智能告警、服务器集群、语音对讲、云台控制、电子地图、H.265自动转码H.264、平台级联等。为了便于用户二次开发、调用与集成&#xff0c;我…

如何入驻抖音本地生活服务商,附上便捷流程!

抖音作为一款短视频社交媒体应用&#xff0c;已经成为全球范围内数以亿计的用户的首选。而在普及的同时&#xff0c;短视频领域也在不断拓展自身的业务领域&#xff0c;其中之一就是本地生活服务。继抖音本地生活服务之后支付宝、视频号也相继开展了本地生活服务&#xff0c;用…

HP惠普暗影精灵7Plus笔记本OMEN 17.3英寸游戏本17-ck0000恢复原厂Windows11预装OEM系统

链接&#xff1a;https://pan.baidu.com/s/1ukMXI2V3D0c-kVmIQSkbYQ?pwd2rbr 提取码&#xff1a;2rbr hp暗影7P原厂WIN11系统适用型号&#xff1a; 17-ck0056TX&#xff0c; 17-ck0055TX&#xff0c; 17-ck0054TX &#xff0c;17-ck0059TX 自带所有驱动、出厂时主题壁纸、…

Oracle实时同步技术

Oracle数据库的价值 Oracle数据库是一种高度可靠、安全和强大的关系型数据库管理系统&#xff0c;它具有以下几个方面的价值&#xff1a; 可靠性和稳定性&#xff1a;Oracle数据库以其高度可靠性、稳定性和数据完整性而闻名于世。 安全性&#xff1a;Oracle数据库提供了一系列…

安装gitlab

安装gitlab 环境 关闭防火墙以及selinux&#xff0c;起码4核8G 内存至少 3G 不然启动不了 下载环境 gitlab官网&#xff1a;GitLab下载安装_GitLab最新中文基础版下载安装-极狐GitLab rpm包下载地址&#xff1a; [Yum - Nexus Repository Manager (gitlab.cn)](https://pack…

【探索嵌入式虚拟化技术与应用】— 虚拟化技术深入浅出自学系列

&#x1f308;个人主页: Aileen_0v0&#x1f525;系列专栏:【探索嵌入式虚拟化技术与应用】&#x1f4ab;个人格言:"没有罗马,那就自己创造罗马~" 目录 一、虚拟技术的发展历史 1.1传统技术的局限性&#xff1a; ​编辑 1.2云计算和万物互联技术的发展机遇&#x…

[JDK工具-3] javac编译器生成class文件 java执行器运行class文件

位置&#xff1a;jdk\bin 语法&#xff1a;javac 源文件 -d class文件输出路径 -encoding utf-8 javac HelloWorld.java -d D:\project1\java8\java8\xin-javademo\src\main\java\com\xin\demo\hutooldemo\ -encoding utf-8 语法&#xff1a;java 类文件完全限定名&#xff08;…

CV计算机视觉每日开源代码Paper with code速览-2023.11.17

点击CV计算机视觉&#xff0c;关注更多CV干货 论文已打包&#xff0c;点击进入—>下载界面 点击加入—>CV计算机视觉交流群 1.【点云分割】&#xff08;CVPR2023&#xff09;Center Focusing Network for Real-Time LiDAR Panoptic Segmentation 论文地址&#xff1a;…

cc linux用root用户执行chmod 777 -R ./提示 Operation not permitted怎么办?

如果你作为 root 用户执行 chmod 777 -R ./ 命令时收到 “Operation not permitted” 错误&#xff0c;可能有几个原因&#xff1a; 不可更改 (Immutable) 文件属性&#xff1a; 文件可能被设置为不可更改。即使是 root 用户也不能修改这些文件的权限。使用 lsattr 命令查看文件…

pr视频剪辑素材,免费下载

找剪辑素材就上这几个网站&#xff0c;视频、音效、图片素材都非常齐全&#xff0c;还能免费下载&#xff0c;赶紧收藏起来。 视频素材 1、菜鸟图库 https://www.sucai999.com/video.html?vNTYxMjky 菜鸟图库网素材非常丰富&#xff0c;网站主要还是以设计类素材为主&#x…

python 实现蚁群算法(simpy带绘图)

这里使用了蚁群算法求解了旅行商问题&#xff0c;同时结合了simpy来绘图 选择下一个食物的函数为&#xff1a; probability[i] pheromone[self.now][self.not_to_foods[i]] ** pheromone_w (1 / distance[self.now][self.not_to_foods[i]]) ** distance_w 该条路概率权重该点…

7.1 Windows驱动开发:内核监控进程与线程回调

在前面的文章中LyShark一直在重复的实现对系统底层模块的枚举&#xff0c;今天我们将展开一个新的话题&#xff0c;内核监控&#xff0c;我们以监控进程线程创建为例&#xff0c;在Win10系统中监控进程与线程可以使用微软提供给我们的两个新函数来实现&#xff0c;此类函数的原…

完全二叉树你需要了解一下

完全二叉树介绍完全二叉树应用场景完全二叉树和满二叉树的区别完全二叉树代码示例拓展 完全二叉树介绍 完全二叉树&#xff08;Complete Binary Tree&#xff09;是一种特殊的二叉树&#xff0c;它的定义是&#xff1a;如果设二叉树的深度为h&#xff0c;除第h层外&#xff0c…

股票扩展功能(十)

A-扩展功能 文章目录 A-扩展功能一. 展示最近10天的斋戒信息, 以 PDF进行预览二. 展示最近10天的斋戒信息, 以 data list 进行响应 一. 展示最近10天的斋戒信息, 以 PDF进行预览 接口描述: 接口地址:/StockApi/extFasting/show 请求方式&#xff1a;GET consumes: produce…

UI for Apache Kafka

文章Overview of UI Tools for Monitoring and Management of Apache Kafka Clusters | by German Osin | Towards Data Science中介绍了8种常见的kafka UI工具,这些产品的核心功能对比信息如下图所示, 通过对比发现 UI for Apache Kafka 功能齐全且免费,因此可以作为我们的首…

gitlab图形化界面使用

gitlab使用 创建用户 上面是创建用户基本操作 修改密码 创建组 给组添加用户 创建项目 选择空白项目 退出root用户&#xff0c;切换其他用户 在服务器上创建ssh密钥 使用ssh-ketgen 命令 新服务器上创建的 [rootgitlab ~]# ssh-keygen Generating public/private rsa key …

uview-plus u-picker的defaultIndexs修改后无效的问题

uniapp项目中使用了uview-plus组件库&#xff0c;在使用u-picker组件时&#xff0c;发现其默认的选中属性 defaultIndex是一次性的&#xff0c;修改后无法响应&#xff0c;解决办法就是在u-picker源码中修改这个属性的watch,源码位置在uni_modules/uview-plus/components/u-pi…

过了那么多1024节才知道……

各位大佬好啊&#xff0c;相信程序员们都知道1024节&#xff0c;那么咱程序员一般会采取什么样的方式来度过程序员节呢&#xff1f;那我们就继续往下看哦&#xff0c;小编包您满意&#xff01; 先来了解一下历史吧&#xff01;1024节的起源可以追溯到2009年&#xff0c;当时俄…