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. (类)Program1.1

    1 class MyClass: 2 3 i = 12345 4 5 def __init__(self): 6 self.data = "WOOWOWOWO" 7 8 def f ...

  2. hdu 1503 Advanced Fruits(DP)

    题意: 将两个英文单词进行合并.[最长公共子串只要保留一份] 输出合并后的英文单词. 思路: 求最长公共子串. 记录路径: mark[i][j]=-1:从mark[i-1][j]转移而来. mark[ ...

  3. MarkDown学习随笔

    MarkDown语法的学习 标题 ​ 设置标题方法是在前面加#号,一级标题(最大)是加#+空格 ,二级标题是加##+空格,之后的以此类推. 字体 在文本的前后分别加上一个星号表示斜体字 在文本的前后分 ...

  4. robot_framewok自动化测试--(1)Robot Framework 环境搭建及常见日志问题解决办法

    一.Robot Framework 介绍 Robot Framework 的架构是一个通用的验收测试和验收测试驱动开发的自动化测试框架(ATDD).它具有易于使用的表格来组织测试过程和测试数据. 它使 ...

  5. logstash写入kakfa数据丢失的问题

    metricbeat采集系统指标,发送到logstash,再写入kafka,发现kafka中的数据不完整,只有某一个指标, 查找原因发现是logstash配置编码问题,如下: input { beat ...

  6. 2020GACTF部分wp

    GACTF misc 签到 给了二维码图 切割再拼上就行 crymisc 给了一个crymisc.docx 无法打开 用file看一下 把后缀名改成zip然后解压 这里奇怪的是用winzip解压会提示 ...

  7. [第二章]c++学习笔记2(类和对象的基础3)

    隐藏的概念 隐藏的作用 使用例 成员函数的重载与缺省(附使用例) 注意事项

  8. 第六周PTA笔记 括号匹配调整+堆放石子+最大积分+168

    括号匹配调整 如果通过插入" +"和" 1"可以从中得到格式正确的数学表达式,则将带括号的序列称为正确的. 例如,序列 "(())()",& ...

  9. 深入理解Spring IOC源码分析

    Spring容器初始化 本文使用的是Spring 5.1.7版本 写在前面:我们看源码一般有3种方式. 第一种直接用class文件,IDEA会帮我们反编译成看得懂的java代码 第二种是用maven的 ...

  10. Android LayoutInflater(布局填充器)

    先来看一下LayoutInflater的基本用法吧,它的用法非常简单,首先需要获取到LayoutInflater的实例,有两种方法可以获取到,第一种写法如下: LayoutInflater layou ...