内容概览
- 批量操作数据
- 批量数据展示
- form组件
- modelform组件
批量操作数据
"""实现浏览器访问一个django路由,立刻创建10万条数据并展示"""
def func(request):
for i in range(100000):
models.Book.objects.create(title=f'第{i}本书') # 在数据库内创建十万条数据
book_obj = modles.Book.objects.all()
return render(request, 'bookList.html', locals())
"""在涉及到大批量数据的创建时,直接使用create创建可能会造成数据库崩溃,所以需要使用其他方法"""
book_list=[]
for i in range(100000):
book_obj = models.Book(title=f'第{i}本书') # 循环创建书籍对象
book_list.append(book_obj) # 将书籍对象添加到列表中
models.Book.objects.bulk_create(book_list) # 批量创建数据
book_query = models.Book.objects.all()
return render(request, 'bookList.html', locals())
"""也可以使用bulk_update()批量修改数据"""
批量数据展示
"""当需要展示的数据量比较大的时候,页面应该考虑分页处理"""
1. 先将数据切片,限制每页展示数量
book_obj = models.Book.objects.all()
current_page = request.GET.get('page', 1) # 当前页数,默认为1
try:
current_page = int(current_page) # 当前页数不是数字时设置为1
except Exception:
current_page = 1
if current_page < 1: # 当前页数小于1时设置为1
current_page = 1
page_show_num = 10 # 每页展示数量
page_start = (current_page - 1) * page_show_num # 起始位置
page_end = page_start + page_show_num # 结束位置
book_obj = book_obj[page_start:page_end] # 切片
2. 在html页面添加分页样式
3. 展示页码
"""使用divmod()方法"""
book_obj_num = models.BookT.objects.all().count() # 统计数据个数
page_num, surplus = divmod(book_obj_num, page_show_num) # 求出商和余数
if surplus: # 如果有余数则页数加1
page_num += 1
page_li_html = ''
# for i in range(1, page_num + 1): # html页面没有range方法,在后端写好后在前端使用safe过滤器
# page_li_html += f'<li><a href="?page={i}">{i}</a></li>'
4. 限制页码展示个数
xxx = current_page
if current_page < 6:
xxx = 6
for i in range(xxx - 5, xxx + 6): # 设置显示范围
if current_page == i:
page_li_html += '<li class="active"><a href="?page=%s">%s</a></li>' % (i, i)
else:
page_li_html += '<li><a href="?page=%s">%s</a></li>' % (i, i)
return render(request, 'func01.html', locals())
form组件
"""编写用户登录功能并且校验数据返回提示信息"""
def ab_form(request):
data_dict = {'username': '', 'password': ''} # 记录报错信息
if request.method == 'POST':
username = request.POST.get('username')
password = request.POST.get('password')
if username == 'jason':
data_dict['username'] = '用户已存在'
if password == '123':
data_dict['password'] = '密码太简单'
return render(request, 'ab_form.html', locals())
"""每次都自己写太过麻烦,使用form组件就能够直接实现"""
form组件功能
- 数据校验:提前设置各种校验规则,然后自动校验
- 渲染页面:可以直接渲染获取用户数据的各种标签
- 展示信息:支持针对不同的校验失败展示不同提示
form类型创建
"""先导入模块"""
from django import forms
class MyForm(forms.Form):
name = forms.CharField(max_length=8, min_length=2) # 最长八个字符,最短两个字符
age = forms.IntegerField(max_value=150, min_value=0) # 数字最大为150,最小为0
email = forms.EmailField() # 必须符合邮箱格式
数据校验功能
1. 传递待校验的数据
form_obj = views.MyForm({'name': 'jason', 'age': 18, 'email': 123})
2. 判断所有的数据是否符合规则
form_obj.is_valid() # False,只要有一个不符合就是False
3. 获取符合校验规则的数据
form_obj.cleaned_data # {'name': 'jason', 'age': 18},只返回符合校验规则的数据
4. 获取不符合校验规则的数据和报错原因
form_obj.errors
"""
<ul class="errorlist">
<li>email
<ul class="errorlist">
<li>Enter a valid email address.
</li>
</ul>
</li>
</ul>
"""
"""
form类中编写的字段如果不填那么肯定无法通过校验
如果多传了字段,多传的字段不会参与校验
"""
渲染标签功能
1. 方式1:
{{ form_obj.as_p }} <!--使用p标签-->
{{ form_obj.as_table }} <!--使用input标签-->
{{ form_obj.as_ul }} <!--使用li标签-->
<!--封装程度高,使用方便;但是扩展性差-->
2. 方式2:
{{ form_obj.name.label }} <!--name字段的名字首字母大写-->
{{ form_obj.name }} <!--input框-->
<!--封装程度低,扩展性好;但是数据过多的情况下编写困难-->
3. 方式3:
{% for form in form_obj %}
{{form.label}}
{{form}}
{% endfor %}
会自动渲染类中的标签样式,其余标签需要自己编写
展示提示信息
html:
浏览器会自动添加数据校验功能,可以设置参数取消该功能:novalidate
<form action='' method='post' novalidate>
{% for form in form_obj %}
<p>
{{ form.label }}{{ form }}
<span style="color: red;">{{ form.errors.0 }}</span> <!--errors.0为错误信息-->
</p>
{% endfor %}
<input type="submit" value="提交">
py:
def func(request):
form_obj = MyForm()
if request.method == 'POST':
form_obj = MyForm(request.POST) # 将前端发送的数据传入forms对象做校验
if form_obj.is_valid(): # 如果校验通过做其他操作,如果没通过则将含带错误信息的对象发送给页面
print(form_obj.cleaned_data)
return render(request, 'func.html', locals())
重要的字段参数
max_length/min_length 最多/最少字符个数
max_value/min_value 最大/最小数字
label 字段注释,设置前端label显示信息
error_messages 设置错误提示
required 设置是否可以为空
widget 可以设置标签类型/标签属性
initial 初始值
validators 正则校验
钩子函数
提供自定义的校验方式,写在Form类里
"""局部钩子:校验单个字段"""
def clean_name(self):
name = self.cleaned_data.get('name') # 钩子函数会在第一层校验完成后再执行
res = models.User.objects.filter(name=name).first()
if res:
return self.add_error('name', '用户名已存在') # 给字段添加报错信息
return name # 需要把取出的数据在传回去
"""全局钩子:校验多个字段"""
def clean(self):
pwd = self.cleaned_data.get('pwd')
confirm_pwd = self.cleaned_data.get('confirm_pwd') # 在form类中添加一个确认密码的字段
if pwd != confirm_pwd:
return self.add_error('confirm_pwd', '两次密码不一致')
return self.confirm_data # 取出全部数据就需要传回所有数据
modelform组件
modelform是form的优化版本,使用更加简单,功能也更强大
class MyModelForm(forms.ModelForm):
class Meta:
model = models.Book # 对应models中的类(表)
fields = "__all__" # 选择字段,__all__表示所有字段
def clean_name(self): # 同样也支持钩子,使用方式与form组件相同
name = self.cleaned_data.get('name')
res = models.User.objects.filter(name=name).first()
if res:
return self.add_error('name', '用户名已存在')
return name
class Meta下常用参数
model 对应models中的类
field 字段,__all__代表所有字段
exclude 排除的字段
labels 提示信息
widgets 自定义插件
error_messaes 自定义错误信息