SweetAlert前端插件

SweetAlert官方使用手册

Django自带的序列化组件

serializers序列化组件可以把我们用ORM产生的QuerySet对象转换成json格式数据。

from django.core import serializers

def index(request):
book_queryset = models.Book.objects.all()
res = serializers.serialize('json', book_queryset)
return HttpResponse(res)

转换后的格式长这样:

批量数据操作

如果我们想要使用ORM去循环插入10万条数据,每次添加数据都执行一次create(),这样会频繁走数据库操作,效率极低,比如:

for i in range(100000):
models.Book.objects.create(title=f'第{i}本书')

这样操作需要等待很久,所以我们可以换一个方法:先用类创建多个对象,在用bulk_create(),这样只要走一次数据库操作就可以添加多个数据了:

obj_list = []  # 存放对象
for i in range(100000):
obj = models.Book(title=f'第{i}本书') # 实例化多个数据对象
obj_list.append(obj) # 对象追加到列表种
models.Book.objects.bulk_create(obj_list) # 一次性全部添加

分页器与推导流程

网站不可能将所有的数据全部展示到一页,应该考虑使用分页,每页只展示部分数据。那么分页该如何实现呢?

推导流程

1.首先需要知道ORM中的all()方法返回的结果集是支持正数的索引切片的。

# 取第一个到第10个的结果
book_queryset = models.Books.objects.all()[0:10]

2.在用户点击分页的页数时肯定是要向后端请求数据的,比如第5页就给前端返回第41到第50的结果(每页展示10条数据的情况),所以后端需要用一个变量接收前端传来的页数。

前端:发送第五页的请求,可以用a标签发送GET请求,并携带数据page=5。

<a href='?page=5'>5</a>

后端:用变量接收

current_page = request.GET.get('page')

3.既然需要分页,那么每页肯定都有最多的展示条数,这里我们设置每页10条,返回指定页数的数据。

def index(request):
current_page = request.GET.get('page')
try: # 异常处理,防止current_page值为空时报错
current_page = int(current_page)
except:
current_page = 1
start = (current_page - 1) * 10 # 数据起始位置
end = current_page * 10 # 数据结束位置
book_queryset = models.Books.objects.all()[start:end]
return render(request, 'index.html', {'book_queryset': book_queryset})

4.前端接收后端数据:

<div class="text-center">
{% for book_obj in book_queryset %}
<p>{{ book_obj.name }}</p>
{% endfor %}
</div>

5.这时候我们只需要在浏览器地址后面输入?page=10,就可以获取第10页的数据。

6.添加Bootstrap提供的分页器

<div class="text-center">
{% for book_obj in book_queryset %}
<p>{{ book_obj.name }}</p>
{% endfor %}
<nav aria-label="Page navigation">
<ul class="pagination">
<li>
<a href="#" aria-label="Previous">
<span aria-hidden="true">&laquo;</span>
</a>
</li>
<li><a href="#">1</a></li>
<li><a href="#">2</a></li>
<li><a href="#">3</a></li>
<li><a href="#">4</a></li>
<li><a href="#">5</a></li>
<li>
<a href="#" aria-label="Next">
<span aria-hidden="true">&raquo;</span>
</a>
</li>
</ul>
</nav>
</div>

7.由于前端不好写动态的分页器,所以我们用后端编写html标签,编写页数时还需要用到divmod()获取所有数据需要的页数,比如99条数据要10页,100条数据要10页,101条数据要11页。

后端:

def index(request):
# 获取当前页数
current_page = request.GET.get('page')
try: # 异常处理,防止current_page值为空时报错
current_page = int(current_page)
except:
current_page = 1
data_queryset = models.Books.objects.all()
start = (current_page - 1) * 10 # 数据起始位置
end = current_page * 10 # 数据结束位置
book_queryset = data_queryset[start:end] data_count = data_queryset.count()
# 接收整数和余数
page_count, m = divmod(data_count, 10)
# 余数不为0,则要把整数部分加一
if m != 0:
page_count += 1
html = []
# 让当前页数左边显示5个页码,右边显示五个页码
for i in range(current_page - 5, current_page + 5):
if i == current_page: # 当前页数高亮显示
html.append(f"<li class='active'><a href='?page={i}'>{i}</a></li>")
else: # 当前页数普通显示
html.append(f"<li><a href='?page={i}'>{i}</a></li>")
return render(request, 'index.html', {'book_queryset': book_queryset, 'html': html})

前端:

<div class="text-center">
{% for book_obj in book_queryset %}
<p>{{ book_obj.name }}</p>
{% endfor %}
<nav aria-label="Page navigation">
<ul class="pagination">
<li>
<a href="#" aria-label="Previous">
<span aria-hidden="true">&laquo;</span>
</a>
</li>
{% for h in html %}
{{ h|safe }}
{% endfor %}
<li>
<a href="#" aria-label="Next">
<span aria-hidden="true">&raquo;</span>
</a>
</li>
</ul>
</nav>
</div>

8.现在可以点击分页器到指定页面了,但是出现了新问题,当前页码小于6时,分页器有零或负数,当前页码过大时,分页器会超出。

这个问题加个变量就可以了。

temp_page = current_page
# 页数过小
if current_page < 6:
temp_page = 6
# 页数过大
if current_page > page_count - 4:
temp_page = page_count - 4
for i in range(temp_page - 5, temp_page + 5):
if i == current_page: # 当前页数高亮显示
html.append(f"<li class='active'><a href='?page={i}'>{i}</a></li>")
else: # 当前页数普通显示
html.append(f"<li><a href='?page={i}'>{i}</a></li>")

究极大法

上面是自定义分页器开发流程的基本思路,我们不需要掌握代码的编写,只需要掌握基本用法即可,原文博客:自定义分页器 - JasonJi - 博客园 (cnblogs.com)

自定义分页器封装代码

点击查看代码
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)

前端使用:

<div class="container">
<div class="row">
<div class="col-md-8 col-md-offset-2">
{% for book in page_queryset %}
<p>{{ book.title }}</p>
{% endfor %}
{{ page_obj.page_html|safe }}
</div>
</div>
</div>

后端使用:

def get_book(request):
book_list = models.Book.objects.all()
current_page = request.GET.get("page", 1)
all_count = book_list.count()
page_obj = Pagination(current_page=current_page, all_count=all_count, per_page_num=10)
page_queryset = book_list[page_obj.start:page_obj.end]
return render(request, 'booklist.html', locals())

Forms组件之创建

Forms组件功能:数据校验、标签渲染、展示信息。

  • 数据校验:数据是否符合规范(长度、格式等)
  • 标签渲染:快速生成输入标签等
  • 信息展示:展示错误的提示信息,并保留原输入内容

基本使用

from django import forms
# 创建表单类
class MyForm(forms.Form):
# 用户名至少三个字符最多八个字符
username = forms.CharField(min_length=3, max_length=8)
# 年龄最小不能小于0 最大不能超过150
age = forms.IntegerField(min_value=0, max_value=150)
# 邮箱必须符合邮箱格式(@关键符号)
email = forms.EmailField()

Forms组件之数据校验

创建好表单类之后,在视图函数中使用:

将数据传入并实例化对象,需要字典类型,字典的键名称与表单类中自定义的名称一致:

form_obj = MyForm({
'username': 'abc',
'age': 999,
'email': '12qq'
})

查看数据是否合法(全部合法结果才是True):

form_obj.isvalid()

查看不符合条件的数据及原因:

form_obj.errors

查看符合条件的数据:

form_obj.cleaned_data

补充

1.forms类中所有的字段数据默认都是必填的,不能少,如果想忽略某些字段,可以添加 required=False。

email = forms.EmailField(required=False)

2.forms类中额外传入的字段数据不会做任何的校验,直接忽略。

Forms组件之渲染标签

后端返回给前端form对象,前端可以使用这个对象创建标签:

def index(request):
form_obj = MyForm()
return render(request, 'index.html', locals())

创建方式一:封装程度高,扩展性较差,主要用于快速生成页面测试功能

1.每一个输入框占一行

<form action="" method="post">
{{ form_obj.as_p }}
<input type="submit">
</form>

2.所有输入框占一行

<form action="" method="post">
{{ form_obj.as_table }}
<input type="submit">
</form>

3.输入框以无序列表形式展示

<form action="" method="post">
{{ form_obj.as_ul }}
<input type="submit">
</form>

创建方式二:封装程度低,扩展性较好,但是字段比较多的情况下不方便。

form对象.字段名.label:文本提示

form对象.字段名:输入标签

<form action="" method="post">

    {{ form_obj.username.label }}
{{ form_obj.username }} {{ form_obj.age.label }}
{{ form_obj.age }} {{ form_obj.email.label }}
{{ form_obj.email }}
<input type="submit">
</form>

创建方式三:创建方式二使用for循环创建

<form action="" method="post">
{% for form in form_obj %}
<p>
{{ form.label }}
{{ form }}
</p>
{% endfor %}
<input type="submit">
</form>

补充

1.forms组件只负责渲染获取用户数据的标签,form表单标签和提交按钮需要自己写。

2.渲染标签中文提示,可以在创建Form类中,创建字段时用参数 label指定,不指定默认使用字段名(首字母大写)。

username = forms.CharField(min_length=3, max_length=8, label='用户名')

Forms组件之信息展示

在你点击提交表单信息后,它会提醒你错误信息:

如果不想要这种提示方式,form表单可以取消浏览器自动添加校验功能的操作:添加属性novalidate。

<form action="" method="post" novalidate>
</form>

这时候前端的校验功能没了,我们可以在后端进行校验:

def index(request):
form_obj = MyForm()
if request.method == 'POST':
# request.POST可以看成字典类型
form_obj = MyForm(request.POST)
# 校验数据
if form_obj.is_valid():
return HttpResponse('数据正常!')
return render(request, 'index.html', locals())

前端使用form.errors.0获取错误信息

<form action="" method="post" novalidate>
{% for form in form_obj %}
<p>
{{ form.label }}
{{ form }}
<span style="color: red">{{ form.errors.0 }}</span>
</p>
{% endfor %}
<input type="submit">
</form>

错误信息是可以自定义的,在Form类中创建字段时定义:

# 用户名至少三个字符最多八个字符
username = forms.CharField(min_length=3, max_length=8, label='用户名',
error_messages={
'min_length': '用户名最短3位',
'max_length': '用户名最长8位',
'required': '用户名必填'
})

Django序列化组件与数据批量操作与简单使用Forms组件的更多相关文章

  1. 如果把父组件的数据实时的传递到子组件:用watch

    1.在子组件使用watch来监听传递给子组件的数据,然后更新子组件的数据. 2.watch和computed结合使用效果非常好. 参考链接:https://blog.csdn.net/zhouweix ...

  2. django基础之day09,Forms组件在程序中做了哪些事? 校验数据、渲染标签、展示信息

    ******************************* Forms组件 *************************************************** Forms组件在 ...

  3. forms组件补充与ModelForm简单使用与cookie与session

    目录 forms组件钩子函数 forms组件字段参数 字段参数 validators详解 choices详解 widget详解 forms组件字段类型 ModelForm简单使用 cookie与ses ...

  4. django中的forms组件

    form介绍 用户需要向后端提交一些数据时,我们常常把这些数据放在一个form表单里,采用form标签,里面包含一些input等标签把用户的数据提交给后端. 在给后端提交数据的时候,我们常常也需要对于 ...

  5. 面向UI编程:ui.js 1.1 使用观察者模式完成组件之间数据流转,彻底分离组件之间的耦合,完成组件的高内聚

    开头想明确一些概念,因为有些概念不明确会导致很多问题,比如你写这个框架为什么不去解决啥啥啥的问题,哎,心累. 什么是框架? 百度的解释:框架(Framework)是整个或部分系统的可重用设计,表现为一 ...

  6. Django组件--forms组件(注册用)

    一.forms组件--校验类的使用 二.form组件--校验类的参数 三.forms组件校验的局部钩子--自定义校验规则(要看源码理解) 四.forms组件校验的全局钩子--校验form表单两次密码输 ...

  7. (32)forms组件(数据校验)

    forms组件的用处 1.就是用来做数据校验的 2.渲染页面 3.渲染错误信息(和局部刷新同效果) 数据校验 要使用forms组件必须要写一个类继承forms组件 urls.py from bbs01 ...

  8. vue组件之间数据的传递

    父子组件通信 父组件向子组件传递数据: 1.通过子组件的 props 选项声明它期待获得的数据,用以接收父组件传过来的值. 2.在子组件标签中使用子组件props中创建的属性 3.父组件中注册子组件 ...

  9. react组件的数据传递

    在react中,为了解决html标签构建应用的不足,将公共的功能单独抽离成一个文件作为一个组件,在使用的地方按需引入,既然是组件彼此调用,就会涉及到父子组件的通信,下面主要来总结简单的组件通信. 1, ...

随机推荐

  1. 网络协议之:socket协议详解之Datagram Socket

    目录 简介 什么是Datagram Socket 使用socat来创建UDP服务 使用ss命令来监控Datagram Sockets 使用nc建立和UDP Socket的连接 总结 简介 上一篇文章我 ...

  2. 记一次dotnet拆分包,并希望得大佬指点

    记一次dotnet拆分包,并希望得大佬指点 之前做了一个用于excel导入导出的包, 定义了一些接口, 然后基于 NPOI EPPlus MiniExcel 做了三种实现 接口大概长下面这样(现在可以 ...

  3. try、catch、finally、return的执行顺序

    1. 不管有没有异常,finally里面的语句都会执行 2. 当try和catch中有返回语句时,finally里面的语句还是会执行 3. 如果finally里面没有return语句,try和catc ...

  4. LC-206

    206. 反转链表 迭代法 class Solution { public ListNode reverseList(ListNode head) { //申请节点,pre和 cur,pre指向nul ...

  5. Oracle临时表空间语句、作用

    在Oracle数据库中:一个表空间只属于一个数据库使用:而一个数据库可以拥有多个表空间.属于"一对多"的关系 我们对照着mysql来理解. 1.Oracle有表空间,mysql没有 ...

  6. 我们如何上传docker到habor上呢

    Docker 打包上传habor认证 首先在 Maven 的配置文件 setting.xml 中增加相关 server 配置,主要配置 Docker registry(远程仓库)用户认证信息. < ...

  7. mybatis plus @TableId注解 type属性的含义

    首先该注解用在主键id上,它的type属性有8种类型 AUTO(0),NONE(1),INPUT(2),ASSIGN_ID(3),ASSIGN_UUID(4),ID_WORKER(3),ID_WORK ...

  8. windows10家庭版启用组策略gpedit.msc

    启用组策略gpedit.msc 家庭版很多功能不能使用,凑巧用的就是家庭版. 还想使用gpedit.msc来关闭windows10的更新. 找到一个可行的方法. 需要创建一个脚本. 如果你没有编辑器, ...

  9. AcWing周赛44

    周赛44 4317. 不同正整数的个数 link:https://www.acwing.com/problem/content/4320/ 我直接set #include <iostream&g ...

  10. k8s入门之基础环境准备(一)

    一.在虚拟机中安装Ubuntu20.04.4系统 1.下载Ubuntu20.04.4服务器版本系统 下载链接地址如下: https://mirrors.tuna.tsinghua.edu.cn/ubu ...