s4 form
- Form
- 需要对请求数据做验证
- 获取到数据然后进行验证
- 解决问题:
- 重复进行用户数据校验:正则,长度,是否为空
- 无法记住上次提交内容,刷新页面数据消失
- 参考博客:
http://www.cnblogs.com/wupeiqi/articles/6144178.html
1. 定义规则
from django.forms import Form
from django.forms import fields
class xxx(Form):
xx = fields.CharField(required=True,max_lenght.,min,error_message=)
2. 使用
# 创建对象:
obj = xxx(request.POST)
# 是否校验成功
v = obj.is_valid()
# html标签name属性 == Form类字段名
# 所有错误信息
obj.errors
# obj.errors['username][0]
# 对象 __str__
# 正确信息
obj.cleaned_data
# 字典
3. 例子
from django.forms import Form
from django.forms import fields
class LoginForm(Form):
username=fields.CharField(
max_length=18,
min_length=6,
required=True,
error_messages={
'required':'不能为空',
'min_length':'不能小于6',
'max_length':'不能大于18',
}
)
password=fields.CharField(min_length=16,required=True)
def login(request):
if request.method=="GET":
return render(request,'login.html')
else:
obj=LoginForm(request.POST)
if obj.is_valid():
print(obj.cleaned_data) #字典
return redirect('http://www.baidu.com')
else:
# print(obj.errors)
#对象 __str__
return render(request,'login.html',{'obj':obj
<form action="/login/"method="POST">
{% csrf_token %}
<p>用户:<input type="text"name="username">{{ obj.errors.username.0 }}</p>
<p> 密码:<input type="password"name="password">{{ obj.errors.password.0 }}</p>
<input type="submit"value="提交">
</form>
- 内部原理
def login(request):
if request.method == 'GET':
return render(request,'login.html')
else:
obj = LoginForm(request.POST)
# is_valid
"""
1. LoginForm实例化时,
self.fields={
'user': 正则表达式
'pwd': 正则表达式
}
2. 循环self.fields
flag = True
errors
cleaned_data
for k,v in self.fields.items():
# 1. user,正则表达式
input_value = request.POST.get(k)
正则表达式和input_value
flag = False
return flag
"""
if obj.is_valid():
print(obj.cleaned_data)
else:
print(obj.errors)
return render(request,'login.html')
- 对用户提交的数据进行校验
- 生成HTML标签
- 保留上次输入的内容
- Form提交验证:(无法保留上次输入内容)
class XXForm(Form):
user = fields.CharField(min_length=8)
email = fields.EmailField()
password = fields.CharField()
phone = fields.RegexField('139\d+')
def login(request):
if request.method == 'GET':
return render(request,'login.html')
else:
obj = LoginForm(request.POST)
if obj.is_valid():
print(obj.cleaned_data)
return redirect('http://www.baidu.com')
return render(request,'login.html',{'obj': obj})
<form id="f1" action="/login/" method="POST">
{% csrf_token %}
<p><input type="text" name="user" />{{ obj.errors.user.0 }}</p>
<p><input type="password" name="pwd" />{{ obj.errors.pwd.0 }}</p>
<input type="submit" value="提交" />
</form>
- Ajax提交验证:
class XXForm(Form):
user = fields.CharField(min_length=8)
email = fields.EmailField()
password = fields.CharField()
phone = fields.RegexField('139\d+')
def ajax_login(request):
import json
ret = {'status': True,'msg': None}
obj = LoginForm(request.POST)
if obj.is_valid():
print(obj.cleaned_data)
else:
# print(obj.errors) # obj.errors对象
ret['status'] = False
ret['msg'] = obj.errors
v = json.dumps(ret)
return HttpResponse(v)
<form id="f1" action="/login/" method="POST">
{% csrf_token %}
<p><input type="text" name="user" /></p>
<p><input type="password" name="pwd" /></p>
<input type="submit" value="提交" />
<a onclick='submitForm():'>提交</a>
</form>
<script src="/static/jquery-1.12.4.js"></script>
<script>
function submitForm(){
$('.c1').remove();
$.ajax({
url: '/ajax_login/',
type: 'POST',
data: $('#f1').serialize(),// user=alex&pwd=456&csrftoen=dfdf\
dataType:"JSON",
success:function(arg){
console.log(arg);
if(arg.status){
}else{
$.each(arg.msg,function(index,value){
console.log(index,value);
var tag = document.createElement('span');
tag.innerHTML = value[0];
tag.className = 'c1';
$('#f1').find('input[name="'+ index +'"]').after(tag);
})
}
}
})
}
</script>
- 保留Form上次输入内容
- 例子:
class RegisterForm(Form):
user = fields.CharField(min_length=8)
email = fields.EmailField()
password = fields.CharField()
phone = fields.RegexField('139\d+')
def register(request):
if request.method=='GET':
obj= RegisterForm()
return render(request,'register.html',{'obj':obj})
else:
obj=RegisterForm(request.POST)
if obj.is_valid():
print(obj.cleaned_data)
else:
print(obj.errors)
return render(request,'register.html',{'obj':obj})
<form action="/register/" method="POST" novalidate>
{% csrf_token %}
<p>{{ obj.user }}{{ obj.errors.user.0 }}</p>
<p>{{ obj.email }}{{ obj.errors.email.0 }}</p>
<p>{{ obj.password }}{{ obj.errors.password.0 }}</p>
<p>{{ obj.phone }}{{ obj.errors.phone.0 }}</p>
<input type="submit"value="提交">
</form>
- Form生成HTML标签
- GET
obj = From()
Form生成HTML标签 <input ‘text’ name='t1' />
- POST
obj = Form(request.POST)
Form生成HTML标签 <input ... value='xx'/>
- Ajax,仅用验证功能
- Form,验证功能,生成HTML标签
- 常用字段:
CharField
...
定义正则表达式
- 字段参数:
-验证:
required
error_message
-生成HTML标签
widget=widgets.select, # 生成标签,推荐使用
# 以下不推荐
label='用户名', # bj.t1.tabel
disabled=True,
label_suffix=':',
initial='666', # 在input中显示默认值
help_text='.....', # 提供帮助信息
- 小结:
class Foo(Form):
user = fields.CharField() # 验证规则,HTML标签插件
obj = Foo(data = request.POST) # 有HTML标签,含有错误信息
obj = Foo(initial = {}) # 只有HTML标签
obj.is_valid()
obj.errors
obj.cleaned_data
a. 多对多
- ChoiceField(可被替代)
- MultiplChoiceField
b. 常用插件
- CheckBox # 复选框
- radio
- input
- textarea
- File
c. 插件示例:
# class TestForm(Form):
# t1 = fields.CharField(
# widget=widgets.Textarea(attrs={})
# widget=widgets.PasswordInput() # 密码输入框
# )
# t2 = fields.CharField(
# widget=widgets.CheckboxInput # 单选框
# )
# t3 =fields.MultipleChoiceField(
# choices=[(1,"篮球"),(2,'足球'),(3,'xxx')],
# widget=widgets.CheckboxSelectMultiple() # 多选
# )
# t4 =fields.ChoiceField(
# choices=[(1,"篮球"),(2,'足球'),(3,'xxx')],
# widget=widgets.RadioSelect # 互斥
# )
# t5 =fields.FileField(
# widget=widgets.FileInput # 文件对象
# )
# def test(request):
# obj=TestForm(initial={'t3':[2,3]})
# return render(request,'test.html',{'obj':obj})
- Select框:
单选
cls_id = fields.IntegerField(
# widget=widgets.Select(choices=[(1,'上海'),(2,'北京')])
widget=widgets.Select(choices=models.Classes.objects.values_list('id','title'),attrs={'class': 'form-control'})
)
cls_id = fields.ChoiceField(
choices=models.Classes.objects.values_list('id','title'),
widget=widgets.Select(attrs={'class': 'form-control'})
)
obj = FooForm({'cls_id':1})
多选
xx = fields.MultipleChoiceField(
choices=models.Classes.objects.values_list('id','title'),
widget=widgets.SelectMultiple
)
obj = FooForm({'cls_id':[1,2,3]})
- 修复Bug,刷新无法动态显示数据库内容:
方式一:不推荐
from django.forms import models as form_model
class TeacherForm(Form):
tname = fields.CharField(min_length=2)
# xx = form_model.ModelMultipleChoiceField(queryset=models.Classes.objects.all())
# xx = form_model.ModelChoiceField(queryset=models.Classes.objects.all())
方式二:
# 单选实现:ChoiceField Select
cls_id=fields.ChoiceField(
# widget=widgets.Select(choices=[(1,'上海'),(2,'北京')])
# widget=widgets.Select(choices=models.Classes.objects.values_list('id','title'),attrs={'class':'form-control'})
widget=widgets.Select(attrs={'class':'form-control'})
)
def __init__(self,*args,**kwargs):
super(StudentForm,self).__init__(*args,**kwargs)
self.fields['cls_id'].choices=models.Classes.objects.values_list('id','title')
# 多选实现:fields.MultipleChoiceField choices
c2t =fields.MultipleChoiceField(
# choices=models.Classes.objects.values_list('id','title'),
widget=widgets.SelectMultiple()
)
def __init__(self,*args,**kwargs):
super(TeacherForm,self).__init__(*args,**kwargs)
self.fields['c2t'].choices=models.Classes.objects.values_list('id','title')
- 拓展
from django.core.exceptions import ValidationError
class TestForm(Form):
user =fields.CharField()
pwd = fields.CharField()
def clean_user(self):
# 验证用户名是否存在
v = self.cleaned_data['user']
if models.Student.objects.filter(name=v).count():
# raise ValidationError('用户名已经存在',code='')
raise ValidationError('用户名已经存在')
return self.cleaned_data['user']
def clean_pwd(self):
return self.cleaned_data['pwd']
def clean(self):
# 所有值进行验证
# hook
user =self.cleaned_data.get('user')
email =self.cleaned_data.get('email')
if models.Student.objects.filter(user=user,email=email).count():
raise ValidationError('用户名邮箱联合已经存在')
return self.cleaned_data
def _post_clean(self):
# 自定制功能,一般用不着
pass
- is_valid 验证:
- 字段 = 默认正则表达式
- 额外的正则
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开头')],
)
- clean_字段,必须返回值
- clean()
有返回值:cleaned_data = 返回值
无返回值:cleaned_data = 原来的值
- Form总结:
1. 使用
class Foo:
xx = xxxxxx() # 正则,插件
def clean_xx():
..
def clean():
pass
2. 页面展示
obj = Foo()
obj = Foo(init..)
# 灵活
<form>
{{obj.xx}}
{{obj.xx}}
</form>
# 简单
{{obj.as_p}}
<ul>
{{obj.as_ul}}
</ul>
<table>
{{obj.as_table}}
</table>
3. 后台
is_valid()
clean_data
errors
- 文件上传
def f1(request):
if request.method=='GET':
return render(request,'f1.html')
else:
import os
# request.POST # 普通文本在此
file_obj=request.FILES.get('fafafa')
print(file_obj.name)
print(file_obj.size)
f = open(os.path.join('static',file_obj.name),'wb')
for chunk in file_obj.chunks():
f.write(chunk)
f.close()
return render(request,'f1.html')
"""
<form method="POST" action="/f1/" enctype="multipart/form-data">
{% csrf_token %}
<input type="text"name="user">
<input type="file"name="fafafa">
<input type="submit"value="提交">
</form>
"""
class F2Form(Form):
user =fields.CharField()
fafafa =fields.FileField()
def f2(request):
if request.method=='GET':
obj = F2Form()
return render(request,'f2.html',{'obj':obj})
else:
obj =F2Form(data=request.POST,files=request.FILES)
if obj.is_valid():
print(obj.cleaned_data.get('fafafa').name)
print(obj.cleaned_data.get('fafafa').size)
return render(request,'f2.html',{'obj':obj})
"""
<form method="POST" action="/f2/" enctype="multipart/form-data">
{% csrf_token %}
{{ obj.user }}
{{ obj.fafafa }}
<input type="submit"value="提交">
</form>
"""