針對一個實例:用戶註冊。css
模型:models.pyhtml
class UserInfo(models.Model): name=models.CharField(max_length=32) pwd=models.CharField(max_length=32) email=models.EmailField() tel=models.CharField(max_length=32)
模板: reg.html:前端
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action="" method="post"> {% csrf_token %} # 爲了經過中間件檢驗 <div> <label for="user">用戶名</label> <p><input type="text" name="name" id="name"></p> </div> <div> <label for="pwd">密碼</label> <p><input type="password" name="pwd" id="pwd"></p> </div> <div> <label for="r_pwd">確認密碼</label> <p><input type="password" name="r_pwd" id="r_pwd"></p> </div> <div> <label for="email">郵箱</label> <p><input type="text" name="email" id="email"></p> </div> <input type="submit"> </form> </body> </html>
視圖函數:regdjango
# forms組件 from django.forms import widgets wid_01=widgets.TextInput(attrs={"class":"form-control"}) wid_02=widgets.PasswordInput(attrs={"class":"form-control"}) class UserForm(forms.Form): name=forms.CharField(max_length=32, widget=wid_01 ) pwd=forms.CharField(max_length=32,widget=wid_02) r_pwd=forms.CharField(max_length=32,widget=wid_02) email=forms.EmailField(widget=wid_01) tel=forms.CharField(max_length=32,widget=wid_01) def register(request): if request.method=="POST": form=UserForm(request.POST) # 生成校驗對象,接受客戶端傳過來的值,進行校驗 if form.is_valid(): # 返回布爾值,校驗的最後結果 print(form.cleaned_data) # 全部經過校驗的字段以及對應的值 else: print(form.cleaned_data) # print(form.errors) # ErrorDict : {"校驗錯誤的字段":["錯誤信息",]} print(form.errors.get("name")) # ErrorList ["錯誤信息",] return HttpResponse("OK") return render(request,"register.html",locals())
重要的點:bootstrap
模板傳過來的字段要和類的字段一一對應。app
能夠多,不能少。函數
若是有沒有的值,即多了不存在字段,不會報錯,不care沒有的鍵值對。可是,若少了必然會是Falsepost
默認都有非空規則,若是須要的匹配的值,有找不到的,就會是False。ui
若是所有正確,纔是Truespa
若是有錯誤的,正確的放在form.cleaned_data,錯誤的放在forms.errors ,錯誤的信息做爲值
forms.error.get(「xxx」)[0]取出錯誤信息,由於其本質的類型是一個字典
form.is_valid() :返回布爾值
form.cleaned_data :{"name":"yuan","email":"123@qq.com"}
form.errors :{"name":[".........."]}
爲了更方便和快捷,以及防止輸入出錯,我麼可使用標籤渲染
form=UserForm
{{form.字段名.lable }}
{{form.字段名 }}
須要在Form類中設置lable屬性,顯示別名(中文名)
view.py中
class UserForm(forms.Form): name=forms.CharField(min_length=4,label='用戶名') pwd=forms.CharField(min_length=4,label='密碼') pwd_r=forms.CharField(min_length=4,label='確認密碼') tel=forms.CharField(label='手機號') email=forms.EmailField(label='郵箱')
reg.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <!-- 最新版本的 Bootstrap 核心 CSS 文件 --> <link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous"> </head> <body> <h3>註冊頁面</h3> <div class="container"> <div class="row"> <div class="col-md-6 col-lg-offset-3"> <form action="" method="post"> {% csrf_token %} <div> <label for="">用戶名</label> {{ form.name }} </div> <div> <label for="">密碼</label> {{ form.pwd }} </div> <div> <label for="">確認密碼</label> {{ form.r_pwd }} </div> <div> <label for=""> 郵箱</label> {{ form.email }} </div> <input type="submit" class="btn btn-default pull-right"> </form> </div> </div> </div> </body> </html>
用for循環動態添加
<form action="" method="post"> {% csrf_token %} {% for field in form %} <div> <label for="">{{ field.label }}</label> {{ field }} </div> {% endfor %} <input type="submit" class="btn btn-default pull-right"> </form>
{{form.as_p }},{{ forms.as_table }},….有不少種
固定了樣式,並且不易於操做,因此不建議使用
<form action="" method="post"> {% csrf_token %} {{ form.as_p }} <input type="submit" class="btn btn-default pull-right"> </form>
views.py
from django.shortcuts import render # Create your views here. from app01.models import * from django import forms from django.forms import widgets # 設置調整渲染的樣式的模塊 # 建立forms組件,用來校驗輸入 class UserForm(forms.Form): name=forms.CharField(min_length=4, # 校驗長度 label='用戶名', # 設置別名 error_messages={"required":'該字段不能爲空'}, # 錯誤信息提示更改成中文 widget=widgets.TextInput(attrs={'class':'form-control'})) # 添加class類的樣式 pwd=forms.CharField(min_length=4,label='密碼', widget=widgets.PasswordInput(attrs={'class':'form-control'}), # 設置成password類型,並添加樣式 error_messages = {"required": '該字段不能爲空'} ) pwd_r=forms.CharField(min_length=4,label='確認密碼', error_messages={"required":'該字段不能爲空'}, widget=widgets.TextInput(attrs={'class':'form-control'}) ) tel=forms.CharField(label='手機號', error_messages={"required":'該字段不能爲空','invalid':'格式錯誤'}, widget=widgets.TextInput(attrs={'class':'form-control'}) ) email=forms.EmailField(label='郵箱', error_messages={"required":'該字段不能爲空','invalid':'格式錯誤'}, widget=widgets.TextInput(attrs={'class':'form-control'}) ) def reg(request): if request.method=="POST": forms=UserForm(request.POST) print('post') if forms.is_valid(): print(forms.cleaned_data) else: print(forms.is_valid()) print(forms.cleaned_data) print(forms.errors) # 重要的一步放在這裏,同時保留了傳過來的值,因此前端在刷新的時候,以前的輸入還會存在 return render(request,'reg.html',locals()) forms=UserForm() return render(request,'reg.html',locals())
模板reg.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" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous"> </head> <body> <h3>渲染方式一</h3> <form action="" method="post" novalidate> {% csrf_token %} <p> {{ forms.name.label }}{{ forms.name }} <span>{{ forms.name.errors.0 }}</span> </p> <p> {{ forms.pwd.label }}{{ forms.pwd }} <span>{{ forms.pwd.errors.0 }}</span> {#.0很重要 取到第一個錯誤,errors獲得的是一個li標籤列表#} </p> <p> {{ forms.pwd_r.label }}{{ forms.pwd_r }} <span>{{ forms.pwd_r.errors.0 }}</span> {#.0很重要#} </p> <p> {{ forms.tel.label }}{{ forms.tel }} <span>{{ forms.tel.errors.0 }}</span> {#.0很重要#} </p> <p> {{ forms.email.label }}{{ forms.email }} <span>{{ forms.email.errors.0 }}</span> {#.0很重要#} </p> <input type="submit"> </form> </body> </html>
模板文件reg.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> .error{ color: red; } </style> <!-- 最新版本的 Bootstrap 核心 CSS 文件 --> <link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous"> </head> <body> <div class="container"> <div class="row"> <div class="col-md-6 col-lg-offset-3"> <hr> <h3>forms組件渲染方式1</h3> <form action="" method="post" novalidate> {% csrf_token %} <p>{{ form.name.label }} {{ form.name }} <span class="pull-right error">{{ form.name.errors.0 }}</span> </p> <p>{{ form.pwd.label }} {{ form.pwd }} <span class="pull-right error">{{ form.pwd.errors.0 }}</span> </p> <p>確認密碼 {{ form.r_pwd }} <span class="pull-right error">{{ form.r_pwd.errors.0 }}</span>
<span class="pull-right error">{{ errors.0 }}</span> {# 全局錯誤 #} </p> <p>郵箱 {{ form.email }} <span class="pull-right error">{{ form.email.errors.0 }}</span></p> <p>手機號 {{ form.tel }} <span class="pull-right error">{{ form.tel.errors.0 }}</span></p> <input type="submit"> </form> </div> </div> </div> </body> </html>
視圖函數views.py
from django.shortcuts import render,HttpResponse # Create your views here. from app01.myforms import * def reg(request): if request.method=="POST": print(request.POST) #form=UserForm({"name":"yu","email":"123@qq.com","xxxx":"alex"}) form=UserForm(request.POST) # form表單的name屬性值應該與forms組件字段名稱一致 print(form.is_valid()) # 返回布爾值 if form.is_valid(): print(form.cleaned_data) # {"name":"yuan","email":"123@qq.com"} else: print(form.cleaned_data) # {"email":123@qq.com} # 全局鉤子錯誤 #print("error",form.errors.get("__all__")[0]) errors=form.errors.get("__all__") return render(request,"reg.html",locals()) form=UserForm() return render(request,"reg.html",locals())
將forms組件邏輯,新建文件單獨放置
from django import forms from django.forms import widgets from app01.models import UserInfo from django.core.exceptions import NON_FIELD_ERRORS, ValidationError class UserForm(forms.Form): name=forms.CharField(min_length=4,label="用戶名",error_messages={"required":"該字段不能爲空"}, widget=widgets.TextInput(attrs={"class":"form-control"}) ) pwd=forms.CharField(min_length=4,label="密碼", widget=widgets.PasswordInput(attrs={"class":"form-control"}) ) r_pwd=forms.CharField(min_length=4,label="確認密碼",error_messages={"required":"該字段不能爲空"},widget=widgets.TextInput(attrs={"class":"form-control"})) email=forms.EmailField(label="郵箱",error_messages={"required":"該字段不能爲空","invalid":"格式錯誤"},widget=widgets.TextInput(attrs={"class":"form-control"})) tel=forms.CharField(label="手機號",widget=widgets.TextInput(attrs={"class":"form-control"})) def clean_name(self): # 局部鉤子 val=self.cleaned_data.get("name") ret=UserInfo.objects.filter(name=val) if not ret: return val else: raise ValidationError("該用戶已註冊!") def clean_tel(self): # 局部鉤子 val=self.cleaned_data.get("tel") if len(val)==11: return val else: raise ValidationError("手機號格式錯誤") def clean(self): # 全局鉤子 pwd=self.cleaned_data.get('pwd') r_pwd=self.cleaned_data.get('r_pwd') if pwd and r_pwd: if pwd==r_pwd: return self.cleaned_data else: raise ValidationError('兩次密碼不一致') else: return self.cleaned_data