Django框架的第九次龖鷄
批量插入自定义分页器
1. 自定义分页器思路2. 自定义分页器源码及使用 Forms组件
1. Forms组件介绍2. Forms组件基本使用3. 校验数据4. 渲染标签展示提示信息钩子函数(HOOK)forms组件其他参数及补充知识点
Django框架的第九次龖鷄 批量插入ORM批量插入数据处理(bulk_create)
def ab_pl(request):
book_list = []
for i in range(10000):
book_obj = modes.Book(name = '第%s本书' % i)
book_list.append(book_obj)
# 批量插入数据时, 使用bulk_create能够大大减少操作
models.Book.objects.bulk_create(book_list)
自定义分页器
Django也有内置的分页器模块 但是功能较少代码繁琐不便于使用 1. 自定义分页器思路
1. queryset对象是可以直接切片操作的,因此可以通过切片来控制数据的展出
2. 确定用户要访问那一页 url?page=1
使用page参数来获取
current_page = request.GET.get('page',1) # 默认是第一页
# 获取的数据都是字符串类型需要注意类型转换
3. 自己规定每页展示多少条数据
per_page_num = 10
4. 动态获取切片的起始和结束位置
start_page = (current_page - 1) * per_page_num
stop_page = current_page * per_page_num
5. 获取当前数据的总条数
all_count = book_queryset.count()
6. 确定总共需要多少页才能展示完所有的数据
# 利用python内置函数divmod()
page_count , more = divmod(all_count,per_page_num)
if more:
page_count += 1
7. 前端模板语法没有range功能
可以在后端写好了传递给页面
8. 针对需要展示的页码规划好到底展示多少个页码
# 一般情况下页码的个数设计都是奇数(符合审美标准) eg:11个页码
在当前页减5 加6 确保当前页处于中间位置
可以添加高亮显示
9. 针对页码小于6,处于最后6页的情况下 做特殊处理
2. 自定义分页器源码及使用
注意事项:
在Django框架中,当我们使用非Django内置的第三方功能或者组件代码的时候
通常会建立一个utils文件夹,在该文件夹内对模块进行功能性划分,(utils可以在每个应用下创建,具体)结合实际情况
下方自定义分页器是基于bootstrap样式来的 所以需要你提前导入bootstrap
分页器源码
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)
后端核心代码
def add_book(request):
# 获取所有的book对象
book_queryset = models.Book.objects.all()
# 默认是第一页
current_page = request.GET.get('page',1)
# 统计有多少个book对象
all_count = book_queryset.count()
# 传值生成对象
page_obj = Pagination(current_page=current_page,all_count=all_count)
# 将page_queryset传递到页面
page_queryset = book_queryset[page_obj.start:page_obj.end]
return render(request, 'book_list.html',locals())
前端核心代码
{% for book_obj in page_queryset %}
{{ book_obj.title }}
{% endfor %}
{{ page_obj.page_html|safe }}
效果展示
Forms组件 1. Forms组件介绍forms组件主要功能是django针对前端form表单提交数据进行校验,也是用处最多的功能,另外也有着渲染html代码和展示提示信息另外两种功能
补充: 为什么数据校验非要去后端,不能在前端利用js直接完成?
数据校验在前端可有可无,但是后端必须要有前端校验是弱不禁风的,可以在页面上直接修改从而跳过校验也可以利用爬虫程序绕过前端页面直接朝后端提交数据 2. Forms组件基本使用
# 写在views.py中
from django import forms
class MyForm(forms.Form):
# username字符串类型最小3位最大8位
username = forms.CharField(min_length=3,max_length=8)
# password字符串类型最小3位最大8位
password = forms.CharField(min_length=3,max_length=8)
# email字段必须符合邮箱格式 xxx@xx.com
email = forms.EmailField()
3. 校验数据
测试环境的准备
pycharm在左下方有一个python console ,是pycharm提供的测试环境
校验数据代码
from app01 import views
1 将带校验的数据组织成字典的形式传入
form_obj = views.MyForm({'username':'xxx','password':'123','email':'123'})
2 判断数据是否合法 (.is_valied) 注意该方法只有在所有的数据全部合法的情况下才会返回True
form_obj.is_valid() # False
3 查看所有校验通过的数据 (.cleaned_data)
form_obj.cleaned_data # {'username':'xxx','password':'123'}
4 查看所有不符合校验规则以及不符合的原因
form_obj.errors # {'email': ['Enter a valid email address.']}
5 校验数据只校验类中出现的字段 多传不影响 多传的字段直接忽略
form_obj = views.MyForm({'username':'xxx','password':'123','email':'123@qq.com','hobby':'study'})
form_obj.is_valid() # True
6 校验数据 默认情况下 类里面所有的字段都必须传值
form_obj = views.MyForm({'username':'xxx','password':'123'})
form_obj.is_valid() # False
"""
也就意味着校验数据的时候 默认情况下数据可以多传但是绝不可能少传
"""
4. 渲染标签
forms组件只会自动渲染获取用户输入的标签(input select radio checkbox),不能渲染提交按钮
- 后端核心代码
def index(request):
1. 先产生一个空对象
from_obj = MyForm()
2. 直接将该空对象传递给html页面
return render(request,'index.html',locals())
- 前端利用空对象三种渲染方式
1. 第一种:代码书写极少 封装程度太高 不便于后续的扩展 一般情况下只在本地测试使用
{{ form_obj.as_p }}
{{ form_obj.as_ul }}
{{ form_obj.as_table}}
2. 第二种:可扩展性很强 但是需要书写的代码太多 一般情况下不用{{ form_obj.username.label }}:{{ form_obj.username }}
{{ form_obj.password.label }}:{{ form_obj.password }}
{{ form_obj.email.label }}:{{ form_obj.email }}
3. 第三种:代码书写简单 并且扩展性也高
{% for form in form_obj %}
{{ form.label }}:{{ form }}
{% endfor %}
展示提示信息label属性默认展示的是类中定义的字段首字母大写的形式
也可以自己修改 直接给字段对象加label属性即可
username = forms.CharField(min_length=3,max_length=8,label=‘用户名’)
注意:
- 必备条件 get请求和post传给html页面对象变量名必须一样forms组件当你的数据不合法的情况下 会保存你上次的数据
后端核心代码:
def index(request):
# 1. 先产生一个空对象
form_obj = MyForm()
if request.method == 'POST':
# 获取用户数据并校验
"""
数据校验注意事项:
1. 数据获取繁琐
2. 校验数据需要构造成字典的格式传入
ps: 但是request.POST 可以看成是一个字典
"""
# 3. 校验数据
form_obj = MyForm(request.POST)
# 4. 判断数据是否合法
if form_obj.is_valid():
# 5. 操作合法 数据存储数据库
return HttpResponse('OK')
# 2. 直接将该空对象传递给html页面
return render(request,'index.html',locals())
前端代码:
展示效果:
补充: 上图效果是浏览器附带的展示错误信息,一般不会采用而是自己定制
让浏览器不做校验方法:



