day12 form组件
day12 form组件
今日内容
- form组件前戏
- form组件基本定义
- form组件数据校验功能
- form组件渲染标签
- form组件提示信息
- 数据校验进阶
- form组件补充
- form组件源码探索
form组件前戏
"""
练习
页面上获取用户输入的用户名和密码
然后判断用户名和密码是否符合一些条件 如果不符合则返回相应的提示信息
"""
自定义数据校验功能 主要步骤
1.搭建前端页面 标签渲染
2.校验数据是否合法 数据校验
3.返回相应的提示信息 提示信息
# 上述的三个步骤form组件都可以自动实现
form组件基本定义
class MyForm(forms.Form):
# username字段最短3位最长8位
username = forms.CharField(min_length=3, max_length=8, label='用户名')
# password字段最短3位最长8位
password = forms.CharField(min_length=3, max_length=8, label='密码')
# email字段必须符合邮箱格式
email = forms.EmailField(label='邮箱') # label参数可以自定义名称
form组件数据校验功能
1、传入待校验的数据
obj = views.MyForm({'username':'meng','password':'123','email':'123@qq.com'})
2、判断所有的数据是否合规 # is_valid()
obj.is_valid() # 结果是布尔值(只有所有的数据全部合规才返回True)
3、 查看符合条件校验的数据
obj.cleaned_data # 返回结果是字典(是所有通过校验的数据)
4、查看不符合条件检验的数据和错误的原因
obj.errors
'''
1.在传递数据的时候,如果多传了额外字段,没有关系,orm不校验
2.form组件内部定义的字段数据 默认都是必填的
可以通过修改参数required=False来控制是否必填
email = forms.EmailField(required=False)
'''
form组件渲染标签
# 第一步先在后端穿衣form对象
def my_form(request):
# 1.生成一个不传参数的form对象
obj = MyForm()
return render(request,'my_form.html',locals())
"""
总结:
自动渲染的标签文本名称默认采用字段名首字母大写的形式
可以通过label参数自定义名称
form只渲染获取用户数据的标签 不渲染提交按钮 需要我们自己编写
"""
前端:
# 渲染标签的方式1
{{ obj.as_p }} # 封装程度太高 扩展不易 通常用于本地测试
{{ obj.as_ul }}
{{ obj.as_table }}
'''
总结:
虽然可以不用自己写就能渲染出用户名等等,
但是无法修改标签,扩展不易
可以使用点as_标签,来决定使用什么标签
'''
# 渲染标签的方式2
<label for="{{ obj.username.id_for_label }}">{{ obj.username.label }}</label>
{{ obj.username }} # 扩展性高 但是书写麻烦
'''
总结:
分两步写的用意是:用户名和输入框是分开的
因为输入框中的id是自动生成的,只能使用参数获取
username.id_for_label:获取uaername的id值绑定给后面的label用户名
达成的效果:点用户名会直接进入到输入框中
'''
# 渲染标签的方式3(使用频率较高)
{% for foo in obj %}
<p>
<label for="{{ foo.id_for_label }}">{{ foo.label }}</label>
{{ foo }} # 融合了方式1和方式2的优势(推荐使用)
</p>
{% endfor %}
'''
总结:
使用for循环可以把定义类中的所有字段都循环出来,不用自己创建
而且 融合了方式1和方式2的优势(推荐使用)
'''
form组件提示信息
1、前端虽然有校验功能,但是太容易修改了,所以取消前端的校验
<form action="" ... novalidate> # form表单中novalidate参数是取消前端校验的
2、form组件如何渲染错误信息
<span>{{ foo.errors.0 }}</span>
# 加上这个会在浏览器中,显示错误信息
3、自定义错误信息
class MyForm(forms.Form):
# username字段最短3位最长8位
username = forms.CharField(min_length=3, max_length=8, label='用户名',
error_messages={
'min_length': '用户名最少3位',
'max_length': '用户名最多8位',
'required': '用户名不能为空'
}
)
# email字段必须符合邮箱格式
email = forms.EmailField(label='邮箱',
error_messages={
'required':'邮箱不能为空',
'invalid':'邮箱格式不正确'
}
)
# 还有一种方法把错误信息变成中文
在settings.py中修改字符编码:LANGUAGE='zh_hans'
'''
总结:
1.先取消前端校验功能,转为后端代码校验
2.在前端中添加{{ foo.errors.0 }}显示错误信息
3.自定义错误信息,用户名和密码的错误信息一致,邮箱设置invalid参数
'''
校验功能的核心逻辑
# views.py
def my_form(request):
# 1.生成一个不传参数的form对象
obj = MyForm()
# 2.判断请求方式
if request.method == 'POST':
print(request.POST) # <QueryDict: {'username': ['meng'], 'password': ['1'], 'email': ['123@qq.com']}>
# 3.直接将数据传入类中
obj = MyForm(request.POST) # 传入参数的obj,必须和上面名字一样
# 4.判断数据是否合规
if obj.is_valid():
print(obj.cleaned_data)
else:
print(obj.errors)
# 5.让前端展示给用户看
return render(request,'my_form.html',locals())
# my_form.html
<form action="" method="post" novalidate> # novalidate:取消校验
{% for foo in obj %}
<p>
<label for="{{ foo.id_for_label }}">{{ foo.label }}</label>
{{ foo }}
<span style="color: red">{{ foo.errors.0 }}</span> # 显示错误信息
</p>
{% endfor %}
<input type="submit" value="提交">
</form>
数据校验进阶
正则校验
from django import forms
from django.core.validators import RegexValidator # 需要导入这个模块才能使用正则
class MyForm(forms.Form):
# phone字段检验手机号是否正确
phone = forms.CharField(label='手机号',
validators=[RegexValidator(r'^[0-9]+$', '请输入数字'),
(r'^(151|176|187|136|166|177|138|)[0-9]{8}$', '请输入正确的手机号')]
)
'''
总结:
使用验证器validators参数,加上
'''
钩子函数之局部钩子
# 钩子函数:基本校验规则之后,产生了cleaned_data数据后才会执行钩子函数
# 局部钩子:校验用户名是否存在
class MyForm(forms.Form):
# 在类中定义函数默认绑定给类
def clean_username(self):
# 获取用户名数据
username = self.cleaned_data.get('username')
# 校验用户名是否已存在
if username == 'meng':
# 添加用户名提示信息
self.add_error('username', '用户名已存在')
# 钩子函数把什么数据勾走,必须返回什么数据
return username
'''
校验用户名时也可以跟数据库里校验
ret = models.User.objects.filter(name=username)
# 判断数据库是否有这个用户名
if not ret:
return username
else:
raise ValidationError("该用户已注册!")
'''
钩子函数之全局钩子
# 全局钩子:多个字段进行校验
# 校验密码与确认密码是否一致
class MyForm(forms.Form):
# 在类中定义函数默认绑定给类
def clean(self): # clean是全局钩子的意思
# 获取密码
password = self.cleaned_data.get('password')
# 获取确认密码
re_password = self.cleaned_data.get('re_password')
# 比对密码是否一致
if not password == re_password:
# 添加提示信息
self.add_error('re_password', '两次密码不一致')
return self.cleaned_data
'''
总结:
add_error:添加提示信息
步骤基本和局部钩子一致,但是返回结果是cleaned_data,固定格式
clean:就是钩注全部的意思,所以要返回全部
'''
form其他组件
initial:初始值
class MyForm(forms.Form):
# username字段最短3位最长8位
username = forms.CharField(
min_length=3,
max_length=8,
label='用户名',
initial='meng' # 加一个默认值
)
error_messages:自定义错误信息
class MyForm(forms.Form):
# username字段最短3位最长8位
username = forms.CharField(
min_length=3,
max_length=8,
label='用户名',
error_messages={ # 自定义错误信息
'min_length': '用户名最少3位',
'max_length': '用户名最多8位',
'required': '用户名不能为空'
}
)
widget:修改标签的属性
class MyForm(forms.Form):
password = forms.CharField(min_length=3,
max_length=8,
label='密码',
# 把密码输入框变成密文,并且里面还可以加bootstrap样式
widget=forms.widgets.PasswordInput(attrs={'class': 'form-control'}),
error_messages={
'min_length': '密码最少3位',
'max_length': '密码名最多8位',
'required': '密码不能为空',
}
)
radioSelec:性别设置
class MyForm(forms.Form):
...
gender = forms.fields.ChoiceField(
choices=((1, "男"), (2, "女"), (3, "保密")),
label="性别",
initial=3,
widget=forms.widgets.RadioSelect()
)
单选Select:单选框
class MyForm(forms.Form):
...
hobby = forms.ChoiceField(
choices=((1, "篮球"), (2, "足球"), (3, "双色球"), ),
label="爱好",
initial=3,
widget=forms.widgets.Select()
)
多选Select:多选框
class MyForm(forms.Form):
...
hobby = forms.MultipleChoiceField(
choices=((1, "篮球"), (2, "足球"), (3, "双色球"), ),
label="爱好",
initial=[1, 3],
widget=forms.widgets.SelectMultiple()
)
单选checkbox
class MyForm(forms.Form):
...
keep = forms.ChoiceField(
label="是否记住密码",
initial="checked",
widget=forms.widgets.CheckboxInput()
)
多选checkbox
class MyForm(forms.Form):
...
hobby = forms.MultipleChoiceField(
choices=((1, "篮球"), (2, "足球"), (3, "双色球"),),
label="爱好",
initial=[1, 3],
widget=forms.widgets.CheckboxSelectMultiple()
)
form组件源码探索
'''阅读源码是提升编程思维的最佳方式!!!'''
# 突破口
# 1.点击is_valid()方法
is_valid()
# 因为cleaned_data和errors,都是通过is_valid()产生的
# 2.查看返回的两个方法
def is_valid(self):
# 如果两个都是True才能返回
return self.is_bound and not self.errors
# is_bound封装的方法
def __init__(self, data=None, files=None, auto_id='id_%s', prefix=None,
# data是传入类中的值,肯定为True
self.is_bound = data is not None or files is not None
# 最后是这三个封装的方法
def full_clean(self):
self._clean_fields()
self._clean_form() # 全局钩子
self._post_clean() # 开放的钩子接口
Django Form所有内置字段
Field
required=True, 是否允许为空
widget=None, HTML插件
label=None, 用于生成Label标签或显示内容
initial=None, 初始值
help_text='', 帮助信息(在标签旁边显示)
error_messages=None, 错误信息 {'required': '不能为空', 'invalid': '格式错误'}
validators=[], 自定义验证规则
localize=False, 是否支持本地化
disabled=False, 是否可以编辑
label_suffix=None Label内容后缀
CharField(Field)
max_length=None, 最大长度
min_length=None, 最小长度
strip=True 是否移除用户输入空白
IntegerField(Field)
max_value=None, 最大值
min_value=None, 最小值
FloatField(IntegerField)
...
DecimalField(IntegerField)
max_value=None, 最大值
min_value=None, 最小值
max_digits=None, 总长度
decimal_places=None, 小数位长度
BaseTemporalField(Field)
input_formats=None 时间格式化
DateField(BaseTemporalField) 格式:2015-09-01
TimeField(BaseTemporalField) 格式:11:12
DateTimeField(BaseTemporalField)格式:2015-09-01 11:12
DurationField(Field) 时间间隔:%d %H:%M:%S.%f
...
RegexField(CharField)
regex, 自定制正则表达式
max_length=None, 最大长度
min_length=None, 最小长度
error_message=None, 忽略,错误信息使用 error_messages={'invalid': '...'}
EmailField(CharField)
...
FileField(Field)
allow_empty_file=False 是否允许空文件
ImageField(FileField)
...
注:需要PIL模块,pip3 install Pillow
以上两个字典使用时,需要注意两点:
- form表单中 enctype="multipart/form-data"
- view函数中 obj = MyForm(request.POST, request.FILES)
URLField(Field)
...
BooleanField(Field)
...
NullBooleanField(BooleanField)
...
ChoiceField(Field)
...
choices=(), 选项,如:choices = ((0,'上海'),(1,'北京'),)
required=True, 是否必填
widget=None, 插件,默认select插件
label=None, Label内容
initial=None, 初始值
help_text='', 帮助提示
ModelChoiceField(ChoiceField)
... django.forms.models.ModelChoiceField
queryset, # 查询数据库中的数据
empty_label="---------", # 默认空显示内容
to_field_name=None, # HTML中value的值对应的字段
limit_choices_to=None # ModelForm中对queryset二次筛选
ModelMultipleChoiceField(ModelChoiceField)
... django.forms.models.ModelMultipleChoiceField
TypedChoiceField(ChoiceField)
coerce = lambda val: val 对选中的值进行一次转换
empty_value= '' 空值的默认值
MultipleChoiceField(ChoiceField)
...
TypedMultipleChoiceField(MultipleChoiceField)
coerce = lambda val: val 对选中的每一个值进行一次转换
empty_value= '' 空值的默认值
ComboField(Field)
fields=() 使用多个验证,如下:即验证最大长度20,又验证邮箱格式
fields.ComboField(fields=[fields.CharField(max_length=20), fields.EmailField(),])
MultiValueField(Field)
PS: 抽象类,子类中可以实现聚合多个字典去匹配一个值,要配合MultiWidget使用
SplitDateTimeField(MultiValueField)
input_date_formats=None, 格式列表:['%Y--%m--%d', '%m%d/%Y', '%m/%d/%y']
input_time_formats=None 格式列表:['%H:%M:%S', '%H:%M:%S.%f', '%H:%M']
FilePathField(ChoiceField) 文件选项,目录下文件显示在页面中
path, 文件夹路径
match=None, 正则匹配
recursive=False, 递归下面的文件夹
allow_files=True, 允许文件
allow_folders=False, 允许文件夹
required=True,
widget=None,
label=None,
initial=None,
help_text=''
GenericIPAddressField
protocol='both', both,ipv4,ipv6支持的IP格式
unpack_ipv4=False 解析ipv4地址,如果是::ffff:192.0.2.1时候,可解析为192.0.2.1, PS:protocol必须为both才能启用
SlugField(CharField) 数字,字母,下划线,减号(连字符)
...
UUIDField(CharField) uuid类型
day12 form组件的更多相关文章
- Django之Form组件
Django之Form组件 本节内容 基本使用 form中字段和插件 自定义验证规则 动态加载数据到form中 1. 基本使用 django中的Form组件有以下几个功能: 生成HTML标签 验证用户 ...
- Python之路【第二十一篇】:Django之Form组件
Django之Form组件 Django的Form主要具有一下几大功能: 生成HTML标签 验证用户数据(显示错误信息) HTML Form提交保留上次提交数据 初始化页面显示内容 小试牛刀 1. ...
- 第十一篇:web之Django之Form组件
Django之Form组件 Django之Form组件 本节内容 基本使用 form中字段和插件 自定义验证规则 动态加载数据到form中 1. 基本使用 django中的Form组件有以下几个功 ...
- 小而美的 React Form 组件
背景 之间在一篇介绍过 Table 组件< React 实现一个漂亮的 Table > 的文章中讲到过,在企业级后台产品中,用的最多且复杂的组件主要包括 Table.Form.Chart, ...
- django框架中的form组件的用法
form组件的使用 先导入: from django.forms import Form from django.forms import fields from django.forms impor ...
- Web框架django[Form]组件
新手上路 Django的Form主要具有一下几大功能: 生成HTML标签 验证用户数据(显示错误信息) HTML Form提交保留上次提交数据 初始化页面显示内容 小试牛刀 1.创建Form类 # 创 ...
- 32.Django form组件
Form组件 Django的Form主要具有一下几大功能: 生成HTML标签 验证用户数据(显示错误信息) HTML Form提交保留上次提交数据 初始化页面显示内容 创建Form类时,主要涉及到 [ ...
- python Django之Form组件
python Django之Form组件 Django的Form主要具有一下几大功能: 生成HTML标签 验证用户数据(显示错误信息) HTML Form提交保留上次提交数据 初始化页面显示内容 小试 ...
- django Form组件 上传文件
上传文件 注意:FORM表单提交文件要有一个参数enctype="multipart/form-data" 普通上传: urls: url(r'^f1/',views.f1), u ...
随机推荐
- PCIE学习笔记--PCIe错误源详解(二)
转载地址:http://blog.chinaaet.com/justlxy/p/5100057799 这篇文章主要介绍事务(Transaction)错误.链路流量控制(Link Flow Contro ...
- 第36篇-return字节码指令
方法返回的字节码相关指令如下表所示. 0xac ireturn 从当前方法返回int 0xad lreturn 从当前方法返回long 0xae freturn 从当前方法返回float 0xaf d ...
- React项目打包并部署到 Github 展示预览效果
React项目打包并部署到 Github 展示预览效果 当开发者模式结束,准备打包的时进行以下步骤: 在package.json配置文件中加一句: "homepage": &quo ...
- EDG夺冠!用Python分析22.3万条数据:粉丝都疯了!
一.EDG夺冠信息 11月6日,在英雄联盟总决赛中,EDG战队以3:2战胜韩国队,获得2021年英雄联盟全球总决赛冠军,这个比赛在全网各大平台也是备受瞩目: 1.微博热搜第一名,截止2021-11-1 ...
- 使用Charles 弱网测试
打开Charles->Proxy→Throttle Settings 1.可以选择不通的网络类型,对于网络的配置一般修改下上行下行即可 2.网络设置各字段解释 bandwidth -- 带宽,即 ...
- Linux usb 4. Device 详解
文章目录 1. 简介 2. Platform Layer 2.1 Platform Device 2.2 Platform Driver 3. UDC/Gadget Layer 3.1 Gadget ...
- Linux usb 2. 协议分析
文章目录 0. 背景 1. USB 协议传输格式 1.1 Packet 1.1.1 Token Packet 1.1.2 Data Packet 1.1.3 Handshake Packet 1.1. ...
- scrapy获取当当网多页的获取
结合上节,网多页的获取只需要修改 dang.py import scrapy from scrapy_dangdang.items import ScrapyDangdang095Item class ...
- 菜鸡的Java笔记 第三十三 - java 泛型
泛型 GenericParadigm 1.泛型的产生动机 2.泛型的使用以及通配符 3.泛型方法的使用 JDK1.5 后的三大主 ...
- ICCV 2021口罩人物身份鉴别全球挑战赛冠军方案分享
1. 引言 10月11-17日,万众期待的国际计算机视觉大会 ICCV 2021 (International Conference on Computer Vision) 在线上如期举行,受到全球计 ...