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. greenplum分布键的hash值计算分析

    greenplum 数据分布策略 greenplum 是一个 MPP 架构的数据库,由一个 master 和多个 segment 组成(还可选配置一个 standby master),其数据会根据设置 ...

  2. Hadoop的安装与部署

    一.硬件及环境 服务器:3台,IP分别为:192.168.100.105.192.168.100.110.192.168.100.115 操作系统:Ubuntu Server 18.04 JDK:1. ...

  3. Bzoj P2054 疯狂的馒头 | 并查集

    题目链接 思路:因为每次染色都会将某些馒头的颜色彻底更改,所以每个馒头的最终的颜色其实是由最后一次染色决定的,那么我们只考虑最后一次染色即可.对此,我们可以从后往前倒着染色,当目前的染色区间中存在白色 ...

  4. Docker的centos镜像内无法使用systemctl命令的解决办法

    在Docker官方的centos镜像内无法使用systemctl命令的解决办法, 使用该命令docker报错 Failed to get D-Bus connection: Operation not ...

  5. matlab与python scipy.signal中 freqs freqz 中w,什么时候是角频率,什么时候是真实的工程中使用的采样频率Hz,如何转化

    matlab与python scipy.signal中的freqs,freqz频率分析函数,输出的w,有时候是角频率,有时候是真实频率,容易搞混,这里对比一下. 0.  精要总结: 1) freqs: ...

  6. java 三大特性_继承、封装、多态_day005

    一.继承: java的三大特性之一.两个类之间通过extends关键字来描述父子关系,子类便可拥有父类的公共方法和公共属性.子类可以继承父类的方法和属性,子类也可以自己定义没有的方法或者通过覆盖父类的 ...

  7. OSI模型 & TCP/IP模型

    分层思想 分层思想:将复杂 的流程分解 为几个功能相对单一 的子过程 整个流程更加清晰 ,复杂问题简单化 更容易发现问题并针对性的解决问题 分层思想在网络中的应用 OSI模型 国际标准化组织(Inte ...

  8. 【Java】数组Array

    Java基础复习之:数组 简介 数组(Array):多个相同数据类型按照一定顺序排列的集合,并使用一个名字命名,通过编号的方式对这些数据进行统一管理 一维数组 一维数组的声明与初始化 int[] id ...

  9. ant生成jmeter测试报告没有数据【已解决】

    1.如下图,在配置build时,到网上找配置文件,配置样式表文件名经常是jmeter-results-detail-report_21.xsl, 3.但是在其他版本可能被不是这个文件名,在jmeter ...

  10. [python]django rest framework写POST和GET接口

    版本声明 python3.6.5 Django-2.0.6 djangorestframework-3.8.2 mysqlclient-1.3.12 1.写一个登录接口,不多说,直接上代码 login ...