一,原始方法的缺陷:
1,用 request.POST.get('变量名') 的方法获取信息,操作重复。
2,没有错误信息的提示
3,没保留上一次提交的数据
二,用户提交数据验证
长度,类型,格式
重用性(多次用到密码,用户名,邮箱等的验证,同一个网站要用相同的验证方法)
解决方法:用一个类实现。
from django import forms #模板 class LoginForm(forms.Form): #模板中的元素 user=forms.CharField(min_length=6,erroe_message={"required":"用户名不能为空","min_length":'长度输入不够'}) #user变量名要与前端的form表单的名称对应一致 email=forms.EmailField(error_message={"required":"邮箱不能为空","invaild":"邮箱格式错误"}) #根据错误信息自定义,提示信息。
def login(request): if request.method=='GET': retrun render(request,'login.html') elif request.method=='POST': obj=LoginForm(request.POST) #实例对象 #验证is_vaild会返回获取的变量与模板的要求是否匹配,返回boolean if obj.is_valid(): #返回.clean返回验证正确的值,用字典的方式 value_dict=obj.clean() else: error_obj=obj.errors.as_json()#获取错误信息,转换为json格式 return render(request,'login.html')
三,当有一个数据输入错误时,其他的信息不会清空,会保留。
1,创建模板 class LoginForm(forms.Form):....
2,将请求交给模板,创建一个对象 obj=LoginForm(request.POST)
3,进行验证 obj.is_valid()
4,获取正确信息 obj.clean()
5,获取错误信息 obj.errors
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Form自动验证</title> </head> <body> <h1>form提交数据</h1> <form method="post" action="/login.html"> <p> {{oo.user}}
//自动的返回html代码,并且会保存上一次的数据 <span>{{oo.errors.user.0}}</span> </p> <p> {{oo.email}} <span>{{oo.errors.email.0}}</span> </p> <p> <input type="text" name="pwd" placeholder="密码" /> </p> <input type="submit" value="提交" /> </form> </body> </html>
处理函数
处理函数 def login(request): if request.method=='GET': obj=LoginForm() return render(request,'login.html',{'oo':obj}) elif request.method=='POST': obj=LoginForm(request.POST) if obj.is_valid(): value_dict=obj.clean() else: error_obj=obj.errors #error_obj['email'][0]是对应错误信息的sstring return render(request,'login.html',{'oo':obj,'value_dict':value_dict,'errors':error_obj})
四,Ajax提交的两种方法
def login_ajax(request): if request.method=='GET': obj=LoginForm() return render(request,'login_ajax.html') elif request.method=='POST': ret={'status':True,'error':None,'data':None} obj=LoginForm(request.POST) if obj.is_valid(): value_dict=obj.clean() else: #方式一 res_str=obj.errors.as_json()#res_str是一个字符串 ret['erroe']=res_str ret['status']=False #方式二 ret['status']=False ret['erroe']=obj.errors.as_data(); #{'user':{ValidationError(['用户名长度不能小于6'])},'email':{ValidationError(['邮箱不能为空'])}} return HttpResponse(json.dump(ret,cls=JsonCustomEncoder))
五,用户验证的参数
1,Django的Form的实现步骤
a ,创建一个验证用户的请求的模板
form django import forms
class MyForm(forms.Form):
user=field.CharField(widget=widgets.TextInput(attrs={'class':'c1','placeholder':'用户名'}))
类:模板的验证类型设置
字段:用于验证用户的某个字段
插件:user=forms.CharField(...,widget=Input框)
设置不同的插件类型,可以实现用户输入的信息进行转换。
b,获取用户的请求,进行验证
is_valid()//该步骤必须要写,开始验证
clean() 获取正确的返回结果
errors错误信息
c,Form提交:
errors.字段.0
ajax提交:
errors.as_json()
errors.as_data()
2,在html的用应用
<!DOCTYPE html> <html lang="zh"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta http-equiv="X-UA-Compatible" content="ie=edge" /> <title>Document</title> </head> <body> <form method="post" action="/field.html"> <label for="{{obj.user.id_for_label}}">{{obj.user.label}}</label> {{obj.user.label_tag}}//与上一排的代码等效,相当于点击文字后input有光标,后台代码,设置了label的属性 {{obj.user}} <input type="submit" value="提交" /> </form> </body> </html>
后台:
#后台代码: class FieldForm(forms.Form): user=fiels.CharField( required=False, initial='小虎', validators=[RegexValidator(r'^[0~9]+$','1111',code='f1'),RegexValidator(r'^158[0~9]+$','2222',code='f2')], error_messages={'required':'不能为空','f1':'f1格式错误','f2':'数字的格式不对'}, #错误信息的优先级是error_messages大于validators,error_messages中的f1是于validators中的code参数一致的。 #错误信息格式:{"user":"[{"message":"f1格式错误","code":"f1"},{"message":"数字的格式不对","code":"f2"}]"}
show_hidden_initial=True label='用户名' )
五,总结
forms与modelform的基类都是BaseForm
以下是字段的用处
class user(models.Model):
u=字段()
a,admin中验证
b,object.clean_fields()
from django.core.handlers.wsgi import WSGIRequest def test(request): #获取请求头信息 #request.environ #获取请求头信息中的访问端的机器型号 #request.environ.get('HTTP_USER_AGENT') obj=models.Test(name='root',email='213') obj.clean_fields() #开始验证 obj.save() return render(request,'test.html')
c,
1,form组件验证
name,email
2,model组件操作数据
name, email
3,modelForm
数据与验证放在一起,耦合太紧了,在django的admin中使用,其余建议分开写
ModelForm组件验证
用户model中的字段
model组件操作数据
name, email
class UserInfoForm(forms.ModelForm): username=forms.CharField(error_message= {'required':"用户名不能为空"}) email=forms.EmailField(error_message= {'invalid':'邮箱格式错误'}) age=forms.IntergeField(inital=1,error_message={'required':'请输入数值'}) class Meta: model=models.UserInfo fields="_all_"
class News(models.Model): title=models.CharField(max_length=64) summary=models.CharField(max_length=128,null=True) url=models.URLField(null=True) ctime=models.DateTimeField(auto_now_add=True) user=models.ForeignKey(to="UserInfo",to_field='nid')//UserInfo是用户信息表 favor=models.ManyToManyField('User',through='Favor',through_field=('news','user')) #manytoMany在admin中管理字段时会有一个下拉框,through是对应的表,through——field是对应的字段 news_type_choices=[ (1,'42区'), (2,'段子'), (3,'图片'), (4,'你问我答'), //由于有固定的类型,可以直接用列表的形式存放 ] nt=models.IntegerField(choices=news_type_choices) favor_count=models.IntegerField(default=0) #关联的第三张表 class Favor(models.Model): new=models.ForeignKey('News') user=models.ForeignKey('User')
验证的顺序是先modelForm再form
六,form验证补充,自定义验证
obj.is_valid()
原码执行顺序:
循环form对象中的所有字段,
for name,field_obj in xx.item
去用户请求中获取数据
1,调用字段的clean方法,进行正则表达式的验证
field_obj.clean(value)
self.clean_[name]() #name是字段名,self是form对象
2,self.clean()
3,_post_clean()
form补充 class UserForm(forms.Form): username=fields.CharField(label="用户名") email=fields.EmailField(label="邮箱") #分字段自定义验证 def clean_username(self): #self是form对象 value=self.cleaned_data['username']#返回的数据都是放在cleaned_data中 if value=='root': return value else: raise ValidationError('验证错误') #抛出异常,会被try捕获 #总体验证,可以抛出异常 def clean(self): v1=self.cleaned_data['username'] v2=self.cleaned_data['email'] if v1=='root' and v2=='root@live.com': pass else: raise ValidationError('用户名或邮箱错误') return self.cleaned_data def _post_clean(self): v1=self.cleaned_data['username'] v2=self.cleaned_data['email'] if v1=='root' and v2=='root@live.com': pass else: self.add_error("__all__",ValidationError('用户名或邮箱错误'))#'__all__'可以用‘None’代替 return self.cleaned_data
七,补充
#连表操作的补充
循环读取数据,多次访问数据库
select_related
主动做连表操作,一次访问数据库表。
select * from user as tb left join user_type on tb.xx=tb1.xx
prefetch_related
select * from user
#用户类型id
selsct * from user_type where id in 用户类型id
model:http://www.cnblogs.com/wupeiqi/articles/6216618.html
form :http://www.cnblogs.com/wupeiqi/articles/6144178.html
modelform:http://www.cnblogs.com/wupeiqi/articles/6229414.html
参照:www.cnblogs.com/wupeiqi/articles/6144178.html