04: Form 验证用户数据 & 生成html
目录:Django其他篇
05:ModelForm 数据验证 & 生成html & 数据库操作
目录:
- 1.1 Form作用 与 基本使用
- 1.2 from内置字段fields(数据验证)、内置插件widgets(生成html)
- 1.3 Form 验证用户数据 & 生成html 使用演示
- 1.4 使用choice字段实现radio,select,checkbox功能
- 1.5 form动态从数据库获取数据添加到select下拉菜单中
- 1.6 form验证规则中的内置钩子
- 1.7 form中自定义验证规则两种方法
1.1 Form作用 与 基本使用返回顶部
1、form 作用
1、功能1: 验证
2、功能2: 生成html标签
3、功能3: HTML Form提交保留上次提交数据
4、功能4: 初始化页面显示内容
2、form使用原则
1、 新url方式操作(一定要用form方式生成html,避免提交刷新页面,丢失当前页面中填的值)
2、 发Ajax请求时可以不用form生成html标签,仅用form做验证,因为ajax请求本身不刷新页面,不必担心填
的值会丢失,当然使用form生成html也是可以的
3、form基本使用:对 login.html提交密码做简单长度验证
from django.shortcuts import render,HttpResponse,redirect
from app01.forms import UserForm def login(request):
if request.method == 'GET':
obj = UserForm()
return render(request,'login.html',{'obj':obj}) elif request.method == 'POST':
obj = UserForm(request.POST)
r1 = obj.is_valid()
if r1:
print(obj.cleaned_data)
else:
print(obj.errors)
return render(request,'login.html',{'obj':obj})
views.py中定义处理函数
from django import forms
from django.forms import fields class UserForm(forms.Form):
#1: 这里的name必须要和input框中name的值
name = fields.CharField(
error_messages={'required':'用户名不能为空'},
) #2: 这里的password必须是input框中name的值
password = fields.CharField(
min_length=6,
max_length=10,
error_messages={'required':'密码不能为空',
'min_length':'密码长度不能小于6',
'max_length':'密码长度不能大于12',
}
)
app01/forms.py中定义字段验证规则
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body> <form method="POST" action="/login/">
<p>用户名:<input name="name" type="text">{{ obj.errors.name.0 }}</p>
<p>密 码:<input name="password" type="text">{{ obj.errors.password.0 }}</p>
<p><input type="submit" value="提交"></p>
</form> </body>
</html>
login.html
4、生成HTML更简单的三种方法,但是耦合性太强,不好定制(不建议使用)
1. { obj.as_p }
2. { obj.as_ul }
3. { obj.as_table }
1.2 from内置字段fields(数据验证)、内置插件widgets(生成html)返回顶部
######################## 1、常用的form内置字段 ######################### #1. 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, # 是否支持本地化(比如需要本地时间而不是utc时间)
disabled=False, # 是否可以编辑
label_suffix=None # Label内容后缀 #2. CharField(Field)
max_length=None, # 最大长度
min_length=None, # 最小长度
strip=True # 是否移除用户输入空白 #3. EmailField(CharField) # 必须为邮件格式 #4. ChoiceField(Field)
choices=(), # 选项,如:choices = ((0,'上海'),(1,'北京'),)
required=True, # 是否必填
widget=None, # 插件,默认select插件
label=None, # Label内容
initial=None, # 初始值
help_text='', # 帮助提示 #5. FileField(Field) # 上传文件
allow_empty_file=False # 是否允许空文件 #6. 时间格式化(必须输入下面要求的格式)
DateField(BaseTemporalField) # 格式:2015-09-01
TimeField(BaseTemporalField) # 格式:11:12
DateTimeField(BaseTemporalField) # 格式:2015-09-01 11:12 ######################## 2、不常用的form内置字段 ######################### #7. IntegerField(Field)
max_value=None, # 最大值
min_value=None, # 最小值 #8. RegexField(CharField) # 自定义正则表达式
regex, # 自定制正则表达式
max_length=None, # 最大长度
min_length=None, # 最小长度
error_message=None, # 忽略,错误信息使用 error_messages={'invalid': '...'} #9. max_value=None, # 最大值
min_value=None, # 最小值
max_digits=None, # 总长度
decimal_places=None, # 小数位长度 #10. ImageField(FileField)上传图片
注:需要PIL模块,pip3 install Pillow
以上两个字典使用时,需要注意两点:
- form表单中 enctype="multipart/form-data"
- view函数中 obj = MyForm(request.POST, request.FILES) #11. BooleanField(Field) # 必须是布尔值 #12. ComboField(Field) # 使用多个验证(比如:即验证最大长度20,又验证邮箱格式)
fields.ComboField(fields=[fields.CharField(max_length=20), fields.EmailField(),]) #13. FilePathField(ChoiceField) # 文件选项,目录下文件显示在页面中
path, # 文件夹路径 #14. GenericIPAddressField
protocol='both', # both,ipv4,ipv6支持的IP格式
unpack_ipv4=False # 解析ipv4地址,如果是::ffff:192.0.2.1时候,可解析为192.0.2.1,
PS:protocol必须为both才能启用 #15. URLField(Field) # 必须是url格式 #16. ModelMultipleChoiceField(ModelChoiceField)
form内置字段(做数据验证)
######################### 1、常用的widgets内置插件 ######################### # TextInput(Input)
# PasswordInput(TextInput)
# EmailInput(TextInput)
# Textarea(Widget)
# FileInput # Select
# SelectMultiple
# RadioSelect
# CheckboxInput
# CheckboxSelectMultiple ######################## 2、不常用的widgets内置插件 ######################### # DateInput(DateTimeBaseInput)
# DateTimeInput(DateTimeBaseInput)
# TimeInput(DateTimeBaseInput) # NumberInput(TextInput)
# URLInput(TextInput) # ClearableFileInput
# MultipleHiddenInput
# SplitDateTimeWidget
# SplitHiddenDateTimeWidget
# SelectDateWidget
# HiddenInput(TextInput)
# NullBooleanSelect
内置插件widgets(生成html)
1.3 Form 验证用户数据 & 生成html 使用演示返回顶部
1、Form验证数据、生成html
from django.shortcuts import HttpResponse,render
from app01 import models
from app01.forms import FM def login(request):
if request.method == 'GET':
obj = FM() # 初始化操作,将字典中的值显示到页面,作为初始化值
return render(request,'login.html',{'obj':obj}) elif request.method == 'POST':
# 获取用户所有数据
# 每条请求数据的验证
# 成功:获取所有正确信息
# 失败:显示错误信息
obj = FM(request.POST,request.FILES) #将POST中提交的所有数据传给处理类(类中做校验)
data = obj.is_valid() #类中对输入信息校验结果,符合返回True,否则返回False
if data:
# obj.cleaned_data 中获取了用户POST中所有正确信息,格式是字典 print(obj.cleaned_data) # 将获取的正确信息字典传入进去就可以直接创建到数据库中
# models.UserInfo.objects.create(**obj.cleaned_data)
else:
print(obj.errors)
return render(request,'login.html',{'obj':obj}) # 法get请求时给页面初始化值
'''
# 从数据库获取数据,传入给initial的值必须是一个字典,且key必须是页面中的字段
dic= {
'user':'tom',
'pwd':'123',
'email':'tom@qq.com',
'city':2,
'mcity':[1,2]
}
# obj = FM(initial=dic) # 初始化操作,将字典中的值显示到页面,作为初始化值
# 为了使用户以get请求也能看到页面内容,在这里也要传入obj
'''
views.py获取前端数据、返回错误信息
from django import forms #我们定义的类必须继承forms.Form
from django.forms import widgets #widgets是插件,可以生成input框
from django.forms import fields #字段 class FM(forms.Form):
# 字段本身自己只做验证
user = fields.CharField(
error_messages={'required':'用户名不能为空'},
label="用户名", #在input框前面添加一个提示信息,比如“用户名”
initial='root', #在input框中可以设置一个默认值
)
pwd = fields.CharField(max_length=12,
min_length=6,
error_messages={'required':'密码名不能为空',
'min_length':'密码长度不能小于6',
'max_length':'密码长度不能大于12'
},
widget=widgets.PasswordInput(attrs={'class':'c1'}), #变成密码input框
)
email = fields.EmailField(error_messages={'required':'邮箱不能为空','invalid':'邮箱格式错误',},
help_text='必须输入邮箱格式'
) f = fields.FileField()
city = fields.ChoiceField(
choices=[(0,'上海'),(1,'广州'),(2,'北京')]
)
mcity = fields.MultipleChoiceField(
choices=[(0,'上海'),(1,'广州'),(2,'北京')]
)
forms.py写form类定义验证规则
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<form action="/login/" method="POST">
<p>{{ obj.user.label }}: {{ obj.user }} {{ obj.errors.user.0 }}</p>
<p>{{ obj.pwd.label }}{{ obj.pwd }} {{ obj.errors.pwd.0 }}</p>
<p>{{ obj.email }} {{ obj.errors.email.0 }} {{ obj.email.help_text }}</p> <p>{{ obj.f }} {{ obj.errors.f.0 }}</p>
<p>{{ obj.p }} {{ obj.errors.p.0 }}</p>
<p>{{ obj.city }} {{ obj.errors.city.0 }}</p>
<p>{{ obj.mcity }} {{ obj.errors.mcity.0 }}</p> <input type="submit" value="提交">
</form> <!-- 1、obj.errors获取到的就是这样的一端html字符串 -->
<!--
1、 obj.user.label 标签显示内容(如:用户名)
obj.user.label_tag
2、 obj.user 自动生成一个input标签,这种表自动保留上一次提交的数据功能
3、 obj.errors.user.0 获取字段错误信息(提取到user字段)
obj.errors 所有字段错误信息的html字符串
obj.user.errors 错误信息(返回html标签)
<ul class="errorlist"><li>用户名不能为空</li></ul>
4、 obj.email.help_text 获取提示帮助信息(必须输入邮箱格式)
--> <!-- 2、obj.errors获取到的就是这样的一端html字符串 -->
<!--
<ul class="errorlist">
<li>user<ul class="errorlist"><li>用户名不能为空</li></ul></li>
<li>pwd<ul class="errorlist"><li>密码名不能为空</li></ul></li>
</ul>
-->
</body>
</html>
login.html生成html
2、生成HTML常用语法
1、 obj.user.label 标签显示内容(如:用户名)
obj.user.label_tag
2、 obj.user 自动生成一个input标签,这种表自动保留上一次提交的数据功能
3、 obj.errors.user.0 获取字段错误信息(提取到user字段)
obj.errors 所有字段错误信息的html字符串
obj.user.errors 错误信息(返回html标签)<ul class="errorlist"><li>用户名不能为空</li></ul>
4、 obj.email.help_text 获取提示帮助信息(必须输入邮箱格式)
3、操作form对象、数据验证
1. obj = FM(request.POST) #将POST中提交的所有数据传给处理类(类中做校验)
2. obj.is_valid() #类中对输入信息校验结果,符合返回True,否则返回False
3. obj.cleaned_data=obj.clean() #用户POST中所有正确信息,格式就是字典
#{'mcity': ['0'], 'user': 'root', 'city': '0', }
4. obj.errors # 所有错误信息的html字符串(ul li格式)
obj.errors.get('user') # user字段错误信息的html字符串(ul li格式)
obj.errors.get('user')[0] #[0]user字段错误信息的错误信息的字符串
1.4 使用choice字段实现radio,select,checkbox功能返回顶部
# 方法1:
user = fields.CharField(
initial=2,
widget=widgets.RadioSelect(choices=((1,'上海'),(2,'北京'),))
) # 方法2:
user = fields.ChoiceField(
choices=((1, '上海'), (2, '北京'),),
initial=2,
widget=widgets.RadioSelect
)
1、单radio,值为字符串的两种写法
# 方法1:
user = fields.CharField(
initial=2,
widget=widgets.Select(choices=((1,'上海'),(2,'北京'),))
) # 方法2:
user = fields.ChoiceField(
choices=((1, '上海'), (2, '北京'),),
initial=2,
widget=widgets.Select
)
2、单select,值为字符串的两种写法
user = fields.MultipleChoiceField(
choices=((1,'上海'),(2,'北京'),),
initial=[1,],
widget=widgets.SelectMultiple
)
3、多选select,值为列表
user = fields.CharField(
widget=widgets.CheckboxInput()
)
4、单checkbox
user = fields.MultipleChoiceField(
initial=[2, ],
choices=((1, '上海'), (2, '北京'),),
widget=widgets.CheckboxSelectMultiple
)
5、多选checkbox,值为列表
1.5 form动态从数据库获取数据添加到select下拉菜单中返回顶部
1、原理介绍
#1 由于user_type是类中的静态字段,程序一启动,就将值放到fields字段中了
#2 所以后面数据库修改后user_type的值还是从fields字段中获取的,必须重启程序才能更新数据到页面
#3 为了实现不必重启程序,我们必须要重写UserInfoForm类的构造方法(每次实例化类都会执行这个构造方法)
#4 每次刷新页面就会调用UserInfoForm类的构造方法,在构造方法中定义每次刷新网页时再从数据库取一次值,将值赋值给fields对应字段
2、实现动态从数据库获取数据添加到select下拉菜单中三种方法
from django.shortcuts import render
from app01 import models def index(request):
from app01.forms import UserInfoForm
obj = UserInfoForm() # 这样就可以实现不必重启服务,数据库更新后前台刷新即可看到新数据
# obj.fields['user_type'].choices = models.UserType.objects.values_list('id','name')
return render(request,'index.html',{'obj':obj})
views.py 中定义处理函数
from django.db import models
from django.db import models class UserType(models.Model):
name = models.CharField(max_length=32)
def __str__(self):
return self.name
models.py中创建usertype表
from django import forms
from django.forms import fields #fields字段专门用于验证
from django.forms import widgets #widgets专门用于生成html标签
from app01 import models class UserInfoForm(forms.Form): # 方法1 和 方法2 需要重写构造方法
user_type1 = fields.ChoiceField(choices=[],widget=widgets.Select)
user_type2 = fields.CharField(widget=widgets.Select(choices=[])) def __init__(self,*args,**kwargs):
super(UserInfoForm,self).__init__(*args,**kwargs)
self.fields['user_type1'].choices = models.UserType.objects.values_list('id','name')
self.fields['user_type2'].widget.choices= models.UserType.objects.values_list('id','name') # 方法3:
from django.forms.models import ModelChoiceField, ModelMultipleChoiceField
# 1 这种方法不必重写构造方法,页面数据库数据就会更新到页面
# 2 但要使用这种方法在创建表的类时必须定义 def __str__(self)
user_type3 = ModelChoiceField(
empty_label='请选择用户类型', #选择框中的提示信息
queryset=models.UserType.objects.all(),
to_field_name='name', #指定那个字段作为value
)
forms.py生成下拉菜单:三种方法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<p>{{ obj.user_type1 }}</p>
<p>{{ obj.user_type2 }}</p>
<p>{{ obj.user_type3 }}</p>
<input type="submit" value="提交">
</body>
</html>
index.html生成html
1.6 form验证规则中的内置钩子返回顶部
1. from验证经历的顺序(搜索:Form and field validation)
1、拿到字段:用户发送一堆数据,根据form循环,拿到第一个字段
2、正则匹配:先进行fields默认正则表达式判断,然后进行自定的正则表达式判断(如果有)
3、字段钩子函数:然后执行字段的钩子函数,接着进行第二个字段,然后是第二个字段钩子函数...
4、clean钩子函数:字段钩子函数执行完了再执行clean钩子函数进行整体验证
5、_post_clean: 最后执行_post_clean钩子做其他验证
2、 form验证的错误信息存放位置
1、字段钩子错误信息放到对应的字段中 (obj.error中对应的字段字典)
2、整体错误信息会放到 {"__all__":[],}中等价于{'NON_FIELD_ERRORS':[],} (如:执行clean)
3、forms.py文件中使用这三种钩子
from django import forms
from django.forms import fields #fields字段专门用于验证
from app01 import models
from django.core.exceptions import ValidationError class RegisterForm(forms.Form):
user = fields.CharField()
email = fields.EmailField()
pwd = fields.EmailField() #1 clean_字段名 是字段钩子(每个字段都有对应的这个钩子):如判断:“用户名已存在”
def clean_user(self):
# self.cleand_data['user']是用户提交的数据'
c = models.User.objects.filter(name=self.cleand_data['user']).count()
if not c:
return self.cleand_data['user'] #必须要有返回值
else:
raise ValidationError('用户名已存在',code='xxx') #2 clean钩子对整体验证:如判断“用户名或密码错误”
def clean(self):
c = models.User.objects.filter(
name=self.cleand_data['user'],
pwd=self.cleand_data['pwd']).count()
if c:
return self.cleand_data #正确的值必须return回去
else:
raise ValidationError('用户名或密码错误') #3 在这里可以做 其他验证
def _post_clean(self):
pass
forms.py文件中使用这三种钩子
1.7 form中自定义验证规则两种方法返回顶部
from django.forms import Form
from django.forms import widgets
from django.forms import fields
from django.core.validators import RegexValidator class MyForm(Form):
user = fields.CharField(
validators=[RegexValidator(r'^[0-9]+$', '请输入数字'),
RegexValidator(r'^159[0-9]+$', '数字必须以159开头')],
)
法1:使用RegexValidator模块进行自定义验证
import re
from django.forms import Form
from django.forms import widgets
from django.forms import fields
from django.core.exceptions import ValidationError # 自定义验证规则
def mobile_validate(value):
mobile_re = re.compile(r'^(13[0-9]|15[012356789]|17[678]|18[0-9]|14[57])[0-9]{8}$')
if not mobile_re.match(value):
raise ValidationError('手机号码格式错误') class PublishForm(Form):
# 使用自定义验证规则
phone = fields.CharField(validators=[mobile_validate, ],
error_messages={'required': '手机不能为空'},
widget=widgets.TextInput(attrs={'class': "form-control",
'placeholder': u'手机号码'}))
法2:使用validators字段自己写函数进行验证
04: Form 验证用户数据 & 生成html的更多相关文章
- Ruby Rails学习中:User 模型,验证用户数据
用户建模 一. User 模型 实现用户注册功能的第一步是,创建一个数据结构,用于存取用户的信息. 在 Rails 中,数据模型的默认数据结构叫模型(model,MVC 中的 M).Rails 为解决 ...
- Django中Form验证
Django的Form主要具有一下几大功能: 生成HTML标签 验证用户数据(显示错误信息) HTML Form提交保留上次提交数据 初始化页面显示内容 一,Form验证 第一种操作:主要是这三个函数 ...
- Django中间件 及 form 实现用户登陆
Django中间件 及 form 实现用户登陆 Form 验证 密码调用md5 加密存储 form.add_error("字段名", "错误信息") 自定义错误 ...
- 使用python抓取婚恋网用户数据并用决策树生成自己择偶观
最近在看<机器学习实战>的时候萌生了一个想法,自己去网上爬一些数据按照书上的方法处理一下,不仅可以加深自己对书本的理解,顺便还可以在github拉拉人气.刚好在看决策树这一章,书里面的理论 ...
- js用正则表达式验证用户和密码的安全性,生成随机验证码
制作了一个表单,表单验证用户.密码.随机验证码 html页面
- python---django中form组件(数据添加前使用自定义方法<django预留扩展点3个>进行验证,以及源码分析)
form组件代码: from app02.models import Userfrom django.core.exceptions import ValidationError class Ajax ...
- 用户数据验证的正确姿势之assert
用户数据验证灰常重要, 不用多说了, 但是实现方法(准确的说是表现形式)有很多人, 如何优雅的完成一个后端验证过滤器是一个值得考量的问题, 我尝试过许多方法, 比如validator.js模块, ex ...
- [oldboy-django][2深入django]老师管理 -- form表单如何生成多选框标签,多选框的默认值显示,以及多选框数据插入到数据库,多选框数据更改到数据库
1 form表单如何生成多选框(包含了多选框可选择内容) - Form设置班级输入框为 select多选 - 多选 class TeacherForm(Form): name = fields.Cha ...
- 在WPF对话框中如何验证用户提供的数据
在WPF中,MS在msdn的WPF应用程序开发中对用户输入的数据验证做了示范,基本思想就是添加各种类型的校验规则,比如最大最小值.字符串长度.是否为空等等,在后在界面绑定数据时添加数据字段的校验.这样 ...
随机推荐
- Scala学习笔记(1)-基本类型归纳
1.小试牛刀 使用Scala自带的REPL shell(Read Evaluate Print Loop)学习和尝试Scala语言库,创建的变量在会话期间都是有效的. Ctrl+D可退出REPL sh ...
- 【转】JavaScript中的匿名函数及函数的闭包
对闭包理解一直不甚明了,在此特转摘博文一篇以备查用. 原文地址:http://www.cnblogs.com/rainman/archive/2009/05/04/1448899.html 相关文章: ...
- 线程池和进程池的通用写法 ProcessPoolExecutor 和 ThreadPoolExecutor
import time from comcurrent.futures import ThreadPoolExecutor,ProcessPoolExccoutor#这个方法可以用进程池或者线程池 d ...
- android Instrumentation 转载
Android提供了一系列强大的测试工具,它针对Android的环境,扩展了业内标准的JUnit测试框架.尽管你可以使用JUnit测试Android工程,但Android工具允许你为应用程序的各个 ...
- UITableView左右滑动cell无法显示“删除”按钮的原因分析
http://www.cocoachina.com/bbs/read.php?tid-145693.html - (void)tableView:(UITableView *)tableView co ...
- php Only variables can be passed by reference
最近做项目,发现了一个报错 Only variables can be passed by reference, 意思是"只有变量能通过'引用'" 就是在代码中 使用了一个方法 ...
- vueawesomeswiper自定义 导航点
1,pagination的配置 pagination: { el: '.swiper-paginationfull', // type:'bullets', // bulletElement : 's ...
- KVM VCPU线程调度问题的讨论
2017-11-15 今天闲着没有突然想了想VCPU线程调度的问题,具体描述如下: 当代表VCPU的线程获得控制权后,首先会通过KVM接口进入到内核,从内核进入到非根模式,那么此时站在全局调度器的点上 ...
- http如何301到https呢?
HTTPS协议的站点信息更加安全,同时可降低网站被劫持的风险,Firefox和chrome浏览器对访问一些非https站点会提示风险,BD等搜索引擎也明确表态了对https站点的友好.那么我们如何部署 ...
- InnoDB: Operating system error number 87 in a file operation. 错误87的解决方法
InnoDB: Operating system error number 87 in a file operation. 错误87的解决方法 140628 8:10:48 [Note] Plugi ...