day12 forms组件
昨日内容复习
-
ajax实现二次确认
1.按钮绑定点击事件
2.判断是否发送ajax请求
数据携带方式注意
1.给按钮绑定点击事件
2.赋值插件代码
3.修改部分内容
-
ajax发送文件数据
先要获取input框用户上传的文件数据 如果获取多个数据 最后面的索引0不需要加
两种方式1.用jquery版本
$('#d1')[0].files[0]
第二种方式使用js代码
document.getElementById('d1').files[0]
产生一个form对象
对象.append('别名',获取数据的values)
formDataObj.append('name',$('#d2').val())
contentType: false,
processData: false,
data:formdata对象
-
datetype参数
后端使用HttpResponse返回的json格式字符串 ,他会自动反序列化成js格式对应的数据类型
后端使用JsonResponse返回的json格式字符串 ,他加不加都行
语法格式:dataType:'JSON' 指定后 后端返回给前端的数据如果不是json格式的 他不会反序列化 会自动区分是不是json格式的
-
序列化组件
from django.core import serializers
res=serializers.serialize('json',books_queryset)
return HttpResponse(res)
序列化其实就是将数据组织成字典并序列化成json格式的过程
from django.core import serializers
-
批量插入(bulk_create)
当需要频繁的插入大量数据的时候可以考虑是该方法 能够极大地提升效率
new_obj_iter=(models.Book(title='第%s本书'%i) for i in range(100000))
models.Book.objects.bulk_create(new_obj_iter)
-
分页
1.需要数据的总量
2.需要定义每页展示多少条
3.需要计算总共需要多少页
4.需要推导出几个核心参数的数学关系
5.需要后端生成html代码
1.前端传给后端要看第几页数据 后端获取请求的页数
2.后端定义页面显示多少数据 起始位置 终止位置 他们是有逻辑关系的
3.后端通过divmod 获取总共多少页 有余数+1
4.后端定义 一个变量=当前页数 判断当前选择的页数小于最小页的中间位置 让这个变量=最小页的中间位置 为了防止左面越界 右面的也设置
5.后端编写HTML代码 for循环 开始位置-5 结束为止+6 设置超链接 并且选择的列高亮显示
6.前端接受数据 for循环数据对象 取title 加上一个分页器bootstrap 引用后面的html代码 实现显示十页
今日内容概要
form组件
是modelform组件的前身 功能更加强大 学完drf再学更容易接受
今日内容详细
form组件前言
low 版本校验
def myform(request):
error_dict={'User_msg':'','Pwd_msg':''}
if request.method=='POST':
username= request.POST.get('username')
password=request.POST.get('password')
if username=='zhang':
error_dict['User_msg']='名字不能是zhang'
if len(password)==0:
error_dict['Pwd_msg']='密码不能为空'
return render(request,'myform.html',locals())
前端需要后面加一个span标签 里面引用后端的error_dict的里面的User_msg 或者Pwd_msg 实现了校验
自定义数据校验功能 主要步骤
1.搭建前端页面 标签渲染
2.校验数据是否合法 数据校验
3.返回相应的提示信息 提示信息
form组件可以自动实现
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/917632e833511c60c8583f2874abeff2.png)
form组件基本定义
与models定义类基本一致
但是这里定义在views视图层
1.先导入
from django import forms
2.定义
class MyFormWow(forms.Form):
username=forms.CharField(max_length=8,min_length=3)
password=forms.CharField(min_length=3,max_length=8)
email=forms.EmailField(required=False))
form组件数据校验功能
from app01 import views
obj=views.MyFormWow({'username':'zhang','password':'123','email':'123@q.com','hobby':'111'})
print(obj.is_valid())
print(obj.cleaned_data)
print(obj.errors)
"""
1.在传递数据的时候 如果多传了额外字段 没有关系 form不校验 不理这个多传入的字段
2.form组件内部定义的字段数据 默认都是必填的
可以通过修改参数required=False来控制是否必填 默认=True 必填
"""
form组件渲染标签功能
def my_form(request):
obj=MyFormWow()
return render(request,'my_form.html',locals())
"""
#自动渲染出在定义类时候 需要用户传的数据对应的标签
自动渲染的标签文本名称默认采用字段名首字母大写的形式
可以通过label参数自定义名称
form只渲染获取用户数据的标签 不渲染提交按钮 需要我们自己编写
"""
{{ obj.as_p }}
{{ obj.as_ul }}
{{ obj.as_table }}
'''
obj.username.label:获取label值
obj.username.id_for_label:获取输入框的id值 这个实现了点前面这个label 光标跳到后面的输入框
obj.username :该输入框
'''
<div>
<label for="{{ obj.username.id_for_label }}">{{ obj.username.label }}</label>
{{ obj.username }}
</div>
<div>
<label for="{{ obj.password.id_for_label }}">{{ obj.password.label }}</label>
{ obj.password }}
</div>
<div>
<label for="{{ obj.email.id_for_label }}">{{ obj.email.label }}</label>
{{ obj.email }}
</div>
{% for foo in obj %}
<p>
<label for="{{ foo.id_for_label }}">{{ foo.label }}</label>
{{ foo }}
</p>
{% endfor %}
form组件数据提示信息功能
在form表单加上一个novalidate 意思是不让前端校验,让后端校验
<form action="" method="post" novalidate>
def my_form(request):
obj=MyFormWow()
if request.method=='POST':
obj=MyFormWow(request.POST)
if obj.is_valid():
print(obj.cleaned_data)
else:
print(obj.errors)
return render(request,'my_form.html',locals())
<span style="color: red">{{ foo.errors.0 }}</span>
error_messages={
'max_length':'用户名最多8位',
'min_length':'用户名最少3位',
'required':'用户名不能为空'
}
邮箱的错误有一点不一样
error_messages={
'required': '邮箱不能为空',
'invalid':'邮箱格式不正确'
}
form组件进阶
数据校验--正则校验
from django.core.validators import RegexValidator
定义一个新的字段
phone=forms.CharField(label='手机号',
validators=[RegexValidator(r'^[0-9]+$', '请输入数字'),
RegexValidator(r'^159[0-9]+$', '数字必须以159开头')
],
)
def clean_username(self):
username=self.cleaned_data.get('username')
if username=='zhang':
self.add_error('username','用户名已存在')
return username
def clean(self):
password=self.cleaned_data.get('password')
confirm_password=self.cleaned_data.get('confirm_password')
if not password==confirm_password:
self.add_error('confirm_password','两次输入密码不一致')
return self.cleaned_data
form组件
label 字段名称
required 是否必填 True必填 False非必填 默认True
initial 默认值
error_messages 自定义错误信息
widget 修改标签的属性 比如type class 等
widget=forms.widgets.PasswordInput()
widget=forms.widgets.TextInput(attrs={'class':'form-control'})
在使用选择标签时,需要注意choices的选项可以配置从数据库中获取,但是由于是静态字段 获取的值无法实时更新,需要重写构造方法从而实现choice实时更新。获取数据库的值给choise赋值
from django.forms import Form
from django.forms import widgets
from django.forms import fields
class MyForm(Form):
user = fields.ChoiceField(
initial=2,
widget=widgets.Select
)
def __init__(self, *args, **kwargs):
super(MyForm,self).__init__(*args, **kwargs)
self.fields['user'].choices = models.Classes.objects.all().values_list('id','caption')
gender = forms.fields.ChoiceField(
choices=((1, "男"), (2, "女"), (3, "其他")),
label="性别",
initial=1,
widget=forms.widgets.RadioSelect()
)
hobby = forms.ChoiceField(
choices=((1, "篮球"), (2, "足球"), (3, "双色球"), ),
label="爱好",
initial=3,
widget=forms.widgets.Select()
)
hobby1 = forms.MultipleChoiceField(
choices=((1, "篮球"), (2, "足球"), (3, "双色球"), ),
label="爱好",
initial=[1, 3],
widget=forms.widgets.SelectMultiple()
)
keep = forms.ChoiceField(
label="是否记住密码",
initial="checked",
widget=forms.widgets.CheckboxInput()
)
hobby2 = forms.MultipleChoiceField(
choices=((1, "篮球"), (2, "足球"), (3, "双色球"),),
label="爱好",
initial=[1, 3],
widget=forms.widgets.CheckboxSelectMultiple()
)
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-S0NAnIjj-1638532360607)(C:\Users\张世虎\AppData\Roaming\Typora\typora-user-images\image-20211203193423777.png)]](https://i-blog.csdnimg.cn/blog_migrate/62397a3617356d0a3c3b55de511a26fe.png)
form组件源码
"""阅读源码是提升编程思维的最佳方式!!!"""
突破口is_valid
---------------------------------------
tmpName = ''
if tmpName:
print('1')
if tmpName is not None:
print('555')
obj=views.MyFormWow()
print(obj.fields)
结果
OrderedDict([('username', <django.forms.fields.CharField object at 0x00000155F91C9580>), ('password', <django.forms.fields.CharField object at 0x00000155F91E3520>), ('confirm_password', <django.forms.fields.CharField object at 0x00000155F91E3670>), ('email', <django.forms.fields.EmailField object at 0x00000155F91E3760>), ('phone', <django.forms.fields.CharField object at 0x00000155F91E3820>)])
拿到了所有字段和数据
for addr,ad in obj.fields.items():
print(addr)
print(ad)