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组件的更多相关文章

  1. Django之Form组件

    Django之Form组件 本节内容 基本使用 form中字段和插件 自定义验证规则 动态加载数据到form中 1. 基本使用 django中的Form组件有以下几个功能: 生成HTML标签 验证用户 ...

  2. Python之路【第二十一篇】:Django之Form组件

    Django之Form组件   Django的Form主要具有一下几大功能: 生成HTML标签 验证用户数据(显示错误信息) HTML Form提交保留上次提交数据 初始化页面显示内容 小试牛刀 1. ...

  3. 第十一篇:web之Django之Form组件

    Django之Form组件   Django之Form组件 本节内容 基本使用 form中字段和插件 自定义验证规则 动态加载数据到form中 1. 基本使用 django中的Form组件有以下几个功 ...

  4. 小而美的 React Form 组件

    背景 之间在一篇介绍过 Table 组件< React 实现一个漂亮的 Table > 的文章中讲到过,在企业级后台产品中,用的最多且复杂的组件主要包括 Table.Form.Chart, ...

  5. django框架中的form组件的用法

    form组件的使用 先导入: from django.forms import Form from django.forms import fields from django.forms impor ...

  6. Web框架django[Form]组件

    新手上路 Django的Form主要具有一下几大功能: 生成HTML标签 验证用户数据(显示错误信息) HTML Form提交保留上次提交数据 初始化页面显示内容 小试牛刀 1.创建Form类 # 创 ...

  7. 32.Django form组件

    Form组件 Django的Form主要具有一下几大功能: 生成HTML标签 验证用户数据(显示错误信息) HTML Form提交保留上次提交数据 初始化页面显示内容 创建Form类时,主要涉及到 [ ...

  8. python Django之Form组件

    python Django之Form组件 Django的Form主要具有一下几大功能: 生成HTML标签 验证用户数据(显示错误信息) HTML Form提交保留上次提交数据 初始化页面显示内容 小试 ...

  9. django Form组件 上传文件

    上传文件 注意:FORM表单提交文件要有一个参数enctype="multipart/form-data" 普通上传: urls: url(r'^f1/',views.f1), u ...

随机推荐

  1. PCIE学习笔记--PCIe错误源详解(二)

    转载地址:http://blog.chinaaet.com/justlxy/p/5100057799 这篇文章主要介绍事务(Transaction)错误.链路流量控制(Link Flow Contro ...

  2. 第36篇-return字节码指令

    方法返回的字节码相关指令如下表所示. 0xac ireturn 从当前方法返回int 0xad lreturn 从当前方法返回long 0xae freturn 从当前方法返回float 0xaf d ...

  3. React项目打包并部署到 Github 展示预览效果

    React项目打包并部署到 Github 展示预览效果 当开发者模式结束,准备打包的时进行以下步骤: 在package.json配置文件中加一句: "homepage": &quo ...

  4. EDG夺冠!用Python分析22.3万条数据:粉丝都疯了!

    一.EDG夺冠信息 11月6日,在英雄联盟总决赛中,EDG战队以3:2战胜韩国队,获得2021年英雄联盟全球总决赛冠军,这个比赛在全网各大平台也是备受瞩目: 1.微博热搜第一名,截止2021-11-1 ...

  5. 使用Charles 弱网测试

    打开Charles->Proxy→Throttle Settings 1.可以选择不通的网络类型,对于网络的配置一般修改下上行下行即可 2.网络设置各字段解释 bandwidth -- 带宽,即 ...

  6. Linux usb 4. Device 详解

    文章目录 1. 简介 2. Platform Layer 2.1 Platform Device 2.2 Platform Driver 3. UDC/Gadget Layer 3.1 Gadget ...

  7. 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. ...

  8. scrapy获取当当网多页的获取

    结合上节,网多页的获取只需要修改 dang.py import scrapy from scrapy_dangdang.items import ScrapyDangdang095Item class ...

  9. 菜鸡的Java笔记 第三十三 - java 泛型

    泛型 GenericParadigm        1.泛型的产生动机        2.泛型的使用以及通配符        3.泛型方法的使用                JDK1.5 后的三大主 ...

  10. ICCV 2021口罩人物身份鉴别全球挑战赛冠军方案分享

    1. 引言 10月11-17日,万众期待的国际计算机视觉大会 ICCV 2021 (International Conference on Computer Vision) 在线上如期举行,受到全球计 ...