python django(forms组件)
forms组件最大的作用,就是做数据校验。
普通做法,一个一个写校验规则,没有解耦。校验规则,都在视图函数里面。
网页校验
修改urls.py,增加路径addbook
from app01 import views
urlpatterns = [
path('admin/', admin.site.urls),
path('index/', views.index),
path('addbook/', views.addbook),
]
修改views.py,增加addbook视图函数,完整代码如下:
from django.shortcuts import render,HttpResponse # Create your views here.
from django import forms # 必须导入模块
class UserForm(forms.Form): # 必须继承Form
#限制数据为字符串,最小长度4,最大长度12
name = forms.CharField(min_length=4,max_length=12)
age = forms.IntegerField() # 限制为数字
#限制长度为11位
tel = forms.CharField(min_length=11,max_length=11) def index(request):
return render(request,"index.html") def addbook(request):
if request.method == "POST":
# 将post数据传给UserForm
form = UserForm(request.POST)
if form.is_valid(): # 验证数据
print("success")
else:
print("fail")
return HttpResponse("ok")
return render(request,"addbook.html")
templates新增addbook.html
做表单校验的时候,一定要注意,表单的name和class的属性必须一一对应
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h3>添加用户</h3>
<form action="" method="post">
{% csrf_token %}
<lable>姓名</lable><input type="text" name="name"/><br/>
<lable>年龄</lable><input type="text" name="age"/><br/>
<lable>邮箱</lable><input type="text" name="email"/><br/>
<lable>手机号码</lable><input type="text" name="tel"/>
<br/>
<input type="submit">
</form>
</body>
</html>
网页访问添加页面,输出信息

提交之后,效果如下:

Pycharm控制台输出:success
空表单直接提交

Pycharm控制台输出:fail
initial 初始值,input框里面的初始值。
error_messages 重写错误信息
form django import forms
from django.core.validators import RegexValidator
from django.core.exceptions import ValidationError
class RegForm(forms.Form): name = forms.Charfield(
initail = 'xxx'
label = '用户名',
min_length = 8,
required = False,
widget = forms.TextInput(attrs={'class':'form-control'})#可以写PasswordInput
#widget=forms.widgets.RadioSelect()单选Select() 多选SelectMultiple()
error_message= {
'min_length':'最小长度为8',
}
#复杂校验
1.直接加自定义验证规则或者写局部钩子
user = fields.CharField(
validators=[RegexValidator(r'^[0-9]+$', '请输入数字'), RegexValidator(r'^159[0-9]+$', '数字必须以159开头')],
)
) def clean_tel(self):#局部钩子
val = self.cleaned_data.get("tel")
if len(val) == 11: # 判断长度
return val
else:
raise ValidationError("手机号码必须11位") def clean_name(self):
# self.cleaned_data.get('name') # 校验成功 返回当前字段值
# 不成功 抛出异常
raise ValidationError() def clean(self):
# 校验成功 返回所有的值
# 不成功 抛出异常
self.add_error('字段','错误信息')
raise ValidationError() def clean(self): # 全局钩子
pwd = self.cleaned_data.get("pwd")
r_pwd = self.cleaned_data.get("r_pwd")
if pwd and r_pwd and pwd != r_pwd: # 判断2次密码不为空,并且2次密码不相等
raise ValidationError("两次密码不一致")
else:
return self.cleaned_data # 这句是固定写法,不能变动
form.is_valid() 它做了2件事情:
1.将数据传给form
2.将验证数据拆分到2个容器中
self.cleaned_data= {} 表示干净的数据
self.error = {} 表示验证不通过的数据
self表示UserForm类的实例对象
as_p是一个特殊的属性,常见的有:
{{ form.as_table }}以表格的形式将它们渲染在<tr>标签中{{ form.as_p }}将它们渲染在<p>标签中{{ form.as_ul }}将它们渲染在<li>标签中
Widgets
Widget 是Django 对HTML 输入元素的表示。Widget 负责渲染HTML和提取GET/POST 字典中的数据。
如果你想让某个Widget 实例与其它Widget 看上去不一样,你需要在Widget 对象实例化并赋值给一个表单字段时指定额外的属性(以及可能需要在你的CSS 文件中添加一些规则)
注意:当input属性为password时,是不会渲染的!除此之外,其他的表单元素,是可以渲染的!
显示错误信息
field.errors 表示错误列表。因为是列表,会有很多错误信息
field.errors.0 表示接收第一个错误信息。一般取第一个即可!
局部钩子与全局钩子
上面提到的校验规则是forms组件自带的。 它做了一些简单的校验功能,比如判断字符串,纯数字,邮箱等等。
比如要求用户名,必须包含字母和数字。年龄必须要大于18岁,手机号码要以136,137开头...
这些需求,默认的校验规则是做不到的。
def clean_name(self):
val = self.cleaned_data.get("name") # 获取输入的用户名 if not val.isdigit(): # 判断不是数字类型
return val
else:
raise ValidationError("用户名不能是纯数字")
注意:
clean_name 这个名字是有含义的,不能随便定义。name表示UserForm类的属性。clean表示校验
val 表示用户输入的用户名
val.isdigit() 表示判断输入的是否为数字,必须return 一个值
raise 表示主动报错,必须接ValidationError。
局部钩子只能校验一个字段,那么2个字段校验呢?比如密码和确认密码必须一致,这个时候,需要使用全局钩子
如何定义全局钩子呢?查看源代码
is_valid()-->self.errors-->self.full_clean()-->self._clean_form()-->self.clean()
Django内置字段
Field
required=True, 是否允许为空
widget=None, HTML插件
label=None, 用于生成Label标签或显示内容
initial=None, 初始值
help_text='', 帮助信息(在标签旁边显示)
error_messages=None, 错误信息 {'required': '不能为空', 'invalid': '格式错误'}
show_hidden_initial=False, 是否在当前插件后面再加一个隐藏的且具有默认值的插件(可用于检验两次输入是否一直)
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类型
...
Django内置插件
TextInput(Input)
NumberInput(TextInput)
EmailInput(TextInput)
URLInput(TextInput)
PasswordInput(TextInput)
HiddenInput(TextInput)
Textarea(Widget)
DateInput(DateTimeBaseInput)
DateTimeInput(DateTimeBaseInput)
TimeInput(DateTimeBaseInput)
CheckboxInput
Select
NullBooleanSelect
SelectMultiple
RadioSelect
CheckboxSelectMultiple
FileInput
ClearableFileInput
MultipleHiddenInput
SplitDateTimeWidget
SplitHiddenDateTimeWidget
SelectDateWidget
实例案例
urls.py
urlpatterns = [
# url(r'^admin/', admin.site.urls),
url(r'^index/', views.index),
url(r'^adduser/', views.adduser),
]
form.py
from django import forms # 必须导入模块
from django.forms import widgets
from django.core.exceptions import NON_FIELD_ERRORS, ValidationError #用于密码验证 class UserForm(forms.Form): # 必须继承Form
# 定义变量,专门给text类型的输入框添加class
wid = widgets.TextInput(attrs={"class": "form-control"})
# 定义字典,错误信息显示中文
# 限制数据为字符串,最小长度4,最大长度12
error_hints = {"required": "该字段不能为空", "invalid": "格式错误!"}
name = forms.CharField(min_length=4, max_length=12, label="姓名", widget=wid, error_messages=error_hints)
# 密码字段
pwd = forms.CharField(label="密码", widget=widgets.PasswordInput(attrs={"class": "form-control"}),
error_messages=error_hints) r_pwd = forms.CharField(label="确认密码", widget=widgets.PasswordInput(attrs={"class": "form-control"}),
error_messages=error_hints)
# 限制为数字
age = forms.IntegerField(label="年龄", widget=wid, error_messages=error_hints)
# 限制为邮箱格式
email = forms.EmailField(label="邮箱", widget=widgets.EmailInput(attrs={"class": "form-control"}),
error_messages=error_hints)
# 限制长度为11位
tel = forms.CharField(max_length=11, label="手机号码", widget=wid, error_messages=error_hints) def clean_name(self): # 校验name值
val = self.cleaned_data.get("name") # 获取输入的用户名 if not val.isdigit(): # 判断数字类型
return val
else:
raise ValidationError("用户名不能是纯数字") def clean_tel(self):
val = self.cleaned_data.get("tel")
if len(val) == 11: # 判断长度
return val
else:
raise ValidationError("手机号码必须11位") def clean_age(self):
val = self.cleaned_data.get("age")
if int(val) > 18: # input输入的值为字符串,必须转换为int
return val
else:
raise ValidationError("年龄必须满18岁以上!") def clean(self): # 全局钩子
pwd = self.cleaned_data.get("pwd")
r_pwd = self.cleaned_data.get("r_pwd")
if pwd and r_pwd and pwd != r_pwd: # 判断2次密码不为空,并且2次密码不相等
raise ValidationError("两次密码不一致")
else:
return self.cleaned_data # 这句是固定写法,不能变动
views.py
from django.shortcuts import render, HttpResponse
from app01.form import UserForm # 导入UserForm类 # Create your views here.
def index(request):
return render(request, "index.html") def adduser(request):
if request.method == "POST":
# 将post数据传给UserForm
form = UserForm(request.POST)
print(request.POST)
if form.is_valid(): # 验证数据 1.将数据传给form 2.将验证数据拆分到2个容器中
print("###success###")
print(form.cleaned_data) # 所有干净的字段以及对应的值
# ErrorDict : {"校验错误的字段":["错误信息",]}
print(form.errors)#表示验证不通过的数据
print(type(form.errors)) # 打印类型
return HttpResponse("添加成功")
else:
print("###fail###")
# print(form.cleaned_data)
print(form.errors)
# # 获取email错误信息,返回一个错误列表,可以切片
# print(form.errors.get("email"))
# # 获取第一个错误信息
# print(form.errors.get("email")[0])
g_error = form.errors.get("__all__") # 接收全局钩子错误信息
if g_error: # 判断有错误信息的情况下
g_error = g_error[0] # 取第一个错误信息 # 将form和g_error变量传给adduser.html
return render(request, "adduser.html", {"form": form, "g_error": g_error}) else: # 默认是get请求(地址栏输入访问时)
form = UserForm() # 没有表单数据的form
return render(request, "adduser.html", {"form": form})
adduser.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css">
<style>
.error {
color: red;
}
</style>
</head>
<body> <div class="container">
<div class="row">
<div class="col-md-6 col-md-offset-2">
<h3>添加用户</h3><br/>
<form action="" method="post" novalidate>
{% csrf_token %}
{% for field in form %}
<div class="form-group">
<label for="">{{ field.label }}</label>
{{ field }} <span class="error pull-right">{{ field.errors.0 }}</span>
{% if field.label == "确认密码" %}
<span class="error pull-right">{{ g_error|default_if_none:"" }}</span>
{% endif %}
</div>
{% endfor %}
<br/>
<input type="submit" class="btn btn-success btn-sm">
</form>
</div>
</div>
</div> </body>
</html>
点击提交什么都不输入的情况下

校验

ModelForm
form与model的终极结合。
class BookForm(forms.ModelForm):
class Meta:
model = models.Book
fields = "__all__"
labels = {
"title": "书名",
"price": "价格"
}
widgets = {
"password": forms.widgets.PasswordInput(attrs={"class": "c1"}),
}
class Meta:下常用参数:
model = models.Student # 对应的Model中的类
fields = "__all__" # 字段,如果是__all__,就是表示列出所有的字段
exclude = None # 排除的字段
labels = None # 提示信息
help_texts = None # 帮助提示信息
widgets = None # 自定义插件
error_messages = None # 自定义错误信息
python django(forms组件)的更多相关文章
- Django forms组件里的ChoiceField、ModelChoiceField和ModelMutipleChoiceField的区别
阅读简要 首先我们要明白Django forms组件里的ChoiceField.ModelChoiceField和ModelMutipleChoiceField是继承关系 ChoiceField 1. ...
- Django forms组件与钩子函数
目录 一.多对多的三种创建方式 1. 全自动 2. 纯手撸(了解) 3. 半自动(强烈推荐) 二.forms组件 1. 如何使用forms组件 2. 使用forms组件校验数据 3. 使用forms组 ...
- django ---forms组件
forms组件 本文目录 1 校验字段功能 2 渲染标签功能 3 渲染错误信息功能 4 组件的参数配置 5 局部钩子 6 全局钩子 回到目录 1 校验字段功能 针对一个实例:注册用户讲解. 模型:mo ...
- Python - Django - form 组件内置的正则校验器
app01/models.py: from django.db import models class UserInfo(models.Model): username = models.CharFi ...
- Python - Django - form 组件基本用法
普通 form 表单的处理: reg.html: <!DOCTYPE html> <html lang="en"> <head> <met ...
- Python - Django - form 组件动态从数据库取 choices 数据
app01/models.py: from django.db import models class UserInfo(models.Model): username = models.CharFi ...
- Python - Django - form 组件自定义校验
reg2.html: <!DOCTYPE html> <html lang="en"> <head> <meta charset=&quo ...
- Python - Django - form 组件校验功能
app01/models.py: from django.db import models class UserInfo(models.Model): username = models.CharFi ...
- Python - Django - form 组件常用的字段和字段参数
邮箱: views.py: from django import forms from django.forms import widgets class RegForm(forms.Form): e ...
随机推荐
- IOS判断NSArray是否为空
场景描述:判断一个集合是否为空,如果不为空执行A,如果为空执行B Java实现方法 public void exec(){ List<String> list = this.getCont ...
- Hadoop Compatibility in Flink
18 Nov 2014 by Fabian Hüske (@fhueske) Apache Hadoop is an industry standard for scalable analytical ...
- Spark RDD持久化、广播变量和累加器
Spark RDD持久化 RDD持久化工作原理 Spark非常重要的一个功能特性就是可以将RDD持久化在内存中.当对RDD执行持久化操作时,每个节点都会将自己操作的RDD的partition持久化到内 ...
- idea右键无法新建Java Class
项目中新建目录之后,要在该目录下新增java Class文件,右键——>New发现无对应选项. 原因:新建目录之后需要设置目录作用,从而让idea识别. 方法:File-Project Stru ...
- linux命令之:yum
yum(全称为 Yellow dog Updater, Modified)是一个在Fedora和RedHat以及SUSE中的Shell前端软件包管理器.基於RPM包管理,能够从指定的服务器自动下载RP ...
- CSAPP:第九章 虚拟内存
CSAPP:第九章 虚拟内存 关键点:虚拟内存.物理内存 9.1 物理地址和虚拟地址9.2 地址空间9.3 虚拟内存作为缓存的公工具 9.1 物理地址和虚拟地址 计算机的主存被组织成一个由M个连续 ...
- redis 基本原理及安装
一:什么是redis? Redis 是一个开源的,高性能的,基于键值对的缓存与存储系统.通过提供多种键值数据类型来适应不同场景下的缓存与存储需求. 二:redis数据库有什么优点? Redis数据库中 ...
- OSGI嵌入tomcat应用服务器(gem-web)——tomcat插件环境搭建
相关的资源下载,参考:https://www.cnblogs.com/dyh004/p/10642769.html 新建普通的plugin工程 新建工程运行环境 在工程中,新建运行环境 新建存放运行环 ...
- [转帖]十二 个经典 Linux 进程管理命令介绍
https://www.cnblogs.com/swordxia/p/4550825.html 接了 http referer 头 没法显示图片 可以去原始blog 里面去查看. 随笔- 109 ...
- Unit 6.标准文档流,浮动,清除浮动以及margin塌陷问题
一. 什么是标准文档流 文本流其实就是文档的读取和输出顺序,也就是我们通常看到的由左到右.由上而下的读取和输出形式,在网页中每个元素都是按照这个顺序进行排序和显示的,而float和position两个 ...