Django批量插入数据及分页器

文章目录

  • 一、批量插入数据
  • 二、分页
    • 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>

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

有依次对应关系的数组X、Y、Z,如何排序其中一个X数组,使得另外的数组还与排序完成后的数组相对应(C语言实现)

1. 目的 有依次对应关系的数组X、Y、Z&#xff0c;排序其中一个X数组&#xff0c;使得另外的数组还与排序完成后的数组相对应&#xff0c;并打印出排序完成后的X、Y、Z数组。 2. 具体实现 以下面的这个对应关系为例&#xff0c;进行相应编程实现。 X [3.7,7.7,-6.6,1.5,-4.5…

腾讯云HAI域AI作画

目录 &#x1f433;前言&#xff1a; &#x1f680;了解高性能应用服务 HAI &#x1f47b;即插即用 轻松上手 &#x1f47b;横向对比 青出于蓝 &#x1f424;应用场景-AI作画 &#x1f424;应用场景-AI对话 &#x1f424;应用场景-算法研发 &#x1f680;使用HAI进行…

ChatGPT暂时停止开通plus,可能迎来封号高峰期

前言: 前两日,chat gpt的创始人 San Altman在网上发表了,由于注册的使用量超过了他们的承受能力,为了确保每个人的良好使用体验,chat gpt将暂时停止开通gpt plus。 情况: 前段时间好像出现了官网崩溃的情况,就连api key都受到了影响,所以现在就开始了暂时停止plus的注…

【数据结构】栈详解

目录 1. 前言2. 栈2.1 栈的概念及结构2.2 如何实现栈2.3 数组栈实现2.3.1 top怎么确定2.3.2 栈顶插入2.3.2.1 栈顶插入分析2.3.2.2 栈顶插入代码实现 2.3.3 栈顶删除2.3.4 判空2.3.4.1 分析2.3.4.2 代码实现 2.3.5 栈的元素个数2.3.6 栈销毁2.3.7 栈访问数据 3. 源代码3.1 Stac…

苍穹外卖—解决前端时间属性显示问题

项目场景&#xff1a; 点击员工管理 出现显示时间属性问题 输入员工姓名为zhangsan 现实的时间属性是数组类型 问题描述 提示&#xff1a;这里描述项目中遇到的问题&#xff1a; 例如&#xff1a;数据传输过程中数据不时出现丢失的情况&#xff0c;偶尔会丢失一部分数据 APP …

手把手带你在AutoDL上部署InternLM-Chat-7B Transformers

手把手带你在AutoDL上部署InternLM-Chat-7B Transformers 调用 项目地址&#xff1a;https://github.com/KMnO4-zx/self_llm.git 如果大家有其他模型想要部署教程&#xff0c;可以来仓库提交issue哦~ 也可以自己提交PR&#xff01; InternLM-Chat-7B Transformers 部署调用 环…

【代数学习题4.2】从零理解范数与迹 —— 求数域元素的范数与迹

从零理解范数与迹 —— 求数域元素的范数与迹 写在最前面题目解答 2. 范数 N N N思路求解过程python求解 3. 数域 K K K 的范数 N K N_K NK​思路求解过程Python求解分析解题步骤 4. 迹 T T T求解过程共轭元素计算迹 python求解分析解题步骤 5. 数域 K K K 的迹 T K T_K …

利用 React 和 Bootstrap 进行强大的前端开发

文章目录 介绍React 和 Bootstrap设置环境使用 Bootstrap 创建 React 组件React-Bootstrap 组件结论 介绍 创建响应式、交互式和外观引人入胜的 Web 界面是现代前端开发人员的基本技能。幸运的是&#xff0c;借助 React 和 Bootstrap 等工具的出现&#xff0c;制作这些 UI 变得…

算法设计与分析复习--回溯法(二)

文章目录 上一篇0-1背包问题图着色问题n皇后问题下一篇 上一篇 算法设计与分析复习–回溯&#xff08;一&#xff09; 0-1背包问题 问题描述&#xff1a;给定n中物品和一个背包。物品 i i i 的重量是 w i w_i wi​ &#xff0c;其价格为 v i v_i vi​ , 背包容量为 c c …

speech studio-神经网络定制自己的声音

Speech Studio - 神经网络定制声音 - 概述 (microsoft.com)

Java,数据结构与集合源码,数据结构概述

目录 数据结构概念&#xff1a; 数据结构的研究对象&#xff1a; 研究对象一&#xff0c;数据间逻辑关系&#xff1a; 研究对象二&#xff0c;数据的存储结构&#xff08;或物理结构&#xff09;&#xff1a; 研究对象三&#xff1a;运算结构 数据结构的相关介绍&#xff…

C++初阶--类型模板

文章目录 泛型编程函数模板使用通用加法函数多模板参数必须用实例化 函数模板的原理类模板使用 注意事项 泛型编程 先看一个例子&#xff1a; 这是一些对于Swap重载的函数&#xff0c;区别是类型不同&#xff1b; 虽然能够重载使用&#xff0c;但代码复用率比较低&#xff0c…

C++11新特性 变参模板、完美转发和emplace

#include <iostream> #include <vector> #include <deque> #include <list> #include <algorithm> using namespace std;class student { public:student() {cout << "无参构造函数被调用!" << endl;}student(int age, st…

C++静态链接库的生成以及使用

目录 一.前言二.生成静态链接库三.使用静态链接库四.其他 一.前言 这篇文章简单讨论一下VS如何生成和使用C静态链接库&#xff0c;示例使用VS2022环境。 二.生成静态链接库 先创建C项目-静态库 然后将默认生成的.h和.cpp文件清理干净&#xff0c;当然你也可以选择保留。 然…

Spring:IoC,AOP的简单理解与使用

IoC容器 IoC &#xff0c;Spring全家桶各个功能模块的基础&#xff0c;是创建对象的容器。 IoC概念 控制反转&#xff0c;将对象的创建进行反转&#xff0c;常规情况下对象由开发者手动创建&#xff0c;而使用IoC不再需要创建对象&#xff0c;由IoC容器根据需求自动创建项目…

2023年【上海市安全员C3证】考试内容及上海市安全员C3证复审考试

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 上海市安全员C3证考试内容是安全生产模拟考试一点通总题库中生成的一套上海市安全员C3证复审考试&#xff0c;安全生产模拟考试一点通上上海市安全员C3证作业手机同步练习。2023年【上海市安全员C3证】考试内容及上海…

MyCAT2的主从配置

http://t.csdnimg.cn/KzwDy&#xff08;mysql主从搭建&#xff09; 前提&#xff0c;先搭建好MySQL的主从配置&#xff0c;登录MyCAT 2在MyCAT2里面操作&#xff0c;也就是连接8066这个端口。 一、创建数据源 ​​​​​​​1.创建数据源 添加读写的数据源 /* mycat:createD…

U4_1:图论之DFS/BFS/TS/Scc

文章目录 一、图的基本概念二、广度优先搜索&#xff08;BFS&#xff09;记录伪代码时间复杂度流程应用 三、深度优先搜索&#xff08;DFS&#xff09;记录伪代码时间复杂度流程时间戳结构BFS和DFS比较 四、拓扑排序一些概念有向图作用拓扑排序 分析伪代码时间复杂度彩蛋 五、强…

阿里云oss存储文件上传功能实现(保姆级教程)

先登录&#xff1a; 点击进入控制台 点击左上角导航栏按钮 搜索oss&#xff0c;点击进入 进入之后点击立即开通oss按钮&#xff0c;开通之后点击下图立即创建&#xff0c;弹出创建Bucket 填上Bucket名称&#xff0c;读写权限改为公共读。其他不变点击确定创建&#xff0c;完成…

uniapp、微信小程序返回上页面刷新数据

目录 前言&#xff1a; 方法1&#xff1a; 方法2&#xff1a; 方法3&#xff1a; 前言&#xff1a; 返回上页面刷新数据这个功能主要用于在当前页面点击跳转到另一个页面之后&#xff0c;在另一个页面对数据进行了操作&#xff0c;比如&#xff1a;阅读量&#xff0c;然后返…