modelscss
from django.db import models class UserInfo(models.Model): useranme = models.CharField(max_length=32) password = models.CharField(max_length=32) email = models.EmailField() telephone = models.CharField(max_length=32)
生成數據表html
C:\PycharmProjects\formsdemo>python manage.py makemigrations
C:\PycharmProjects\formsdemo>python manage.py migrate
主urlpython
from django.contrib import admin
from django.urls import path, re_path, include
urlpatterns = [
path('admin/', admin.site.urls),
re_path(r'^', include(('app01.urls', 'app01')))
]
url數據庫
from django.urls import path, re_path, include
from app01 import views
urlpatterns = [
re_path(r'reg/$', views.reg, name='reg'),
]
模板層django
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action="" method="post"> {% csrf_token %} <p>用戶名 <input type="text" name="user"></p> <p>密碼 <input type="password" name="pwd"></p> <p>確認密碼 <input type="password" name="_pwd"></p> <p>郵箱 <input type="text" name="email"></p> <p>手機號 <input type="text" name="tel"></p> <input type="submit" value="註冊"> </form> </body> </html>
viewbootstrap
from django.shortcuts import render, HttpResponse def reg(request): if request.method == 'POST': print(request.POST) return HttpResponse('註冊成功') return render(request, 'reg.html')
<QueryDict: {'csrfmiddlewaretoken': ['5EwZsUEKRVj836bplmS03PVruttZhG'], 'user': ['alex'], 'pwd': ['123'], '_pwd': ['123'], 'email': ['123@qq.com'], 'tel': ['1234566778']}>
from django import forms # 導入forms組件 # 定義校驗規則 class UserForm(forms.Form): name = forms.CharField(min_length=4, max_length=10) email = forms.EmailField()
reg視圖代碼app
from django.shortcuts import render, HttpResponse # Create your views here. from django import forms # 導入forms組件 # 定義校驗規則 class UserForm(forms.Form): name = forms.CharField(min_length=4, max_length=10) email = forms.EmailField() def reg(request): if request.method == 'POST': # 1.form.is_valid() 是否經過驗證 form = UserForm({'name': 'alex', 'email': '123@qq.com'}) print(form.is_valid()) # True 返回布爾值 form = UserForm({'name': 'a', 'email': '123'}) print(form.is_valid()) # False form = UserForm({'name': 'alex', 'email': '123@qq.com', 'age': '33'}) print(form.is_valid()) # True # form = UserForm({'name': 'alex', 'xxx': '123@qq.com'}) print(form.is_valid()) # False form = UserForm({'name': 'a', 'email': '123', 'xxx': '123'}) print(form.is_valid()) # False if form.is_valid(): pass else: pass """ forms組件只會校驗定義過的字段, 定義的data,必須知足條件且存在 True 多餘的字段,不影響 """ return HttpResponse('註冊成功') return render(request, 'reg.html')
from django.shortcuts import render, HttpResponse # Create your views here. from django import forms # 導入forms組件 # 定義校驗規則 class UserForm(forms.Form): name = forms.CharField(min_length=4, max_length=10) email = forms.EmailField() def reg(request): if request.method == 'POST': # 1.form.is_valid() 是否經過驗證 form = UserForm({'name': 'alex', 'email': '123@qq.com'}) print(form.is_valid()) # True 返回布爾值 form = UserForm({'name': 'a', 'email': '123'}) print(form.is_valid()) # False form = UserForm({'name': 'alex', 'email': '123@qq.com', 'age': '33'}) print(form.is_valid()) # True # form = UserForm({'name': 'alex', 'xxx': '123@qq.com'}) print(form.is_valid()) # False form = UserForm({'name': 'a', 'email': '123', 'xxx': '123'}) print(form.is_valid()) # False # 2. form.cleaned_data # form.errors if form.is_valid(): print('cleaned_data1:', form.cleaned_data) print('errors1:', form.errors) else: print('cleaned_data2:', form.cleaned_data) print('errors2:', form.errors) # 取出error——msg print(form.errors.get("name")) print(type(form.errors.get("name"))) # ErrorList print(form.errors.get("name")[0]) # Ensure this value has at least 4 characters (it has 1). """ if 全部字段校驗成功,則 form.cleaned_data: {'name': 'alex', 'email': '123@qq.com'} 只保留定義過的字段 form.errors: 空 if 校驗不成功,則 form.cleaned_data:{'name': 'alex'} 只保留定義過的字段, form.errors: <li>email<ul class="errorlist"> 定義過的字段,未經過的信息 (cleaned_data + errors 之和,一定是定義過的全部字段) """ return HttpResponse('註冊成功') return render(request, 'reg.html')
(1)驗證經過ide
驗證字段函數
(2)驗證不經過post
示例1:驗證字段
示例2:驗證字段
五、取出 forms.error錯誤信息
url
from django.urls import path, re_path, include
from app01 import views
urlpatterns = [
re_path(r'reg_test/$', views.reg_test, name='reg_test'),
]
view
from django.shortcuts import render, HttpResponse from django import forms # 導入forms組件 # 定義校驗規則 class UserForm(forms.Form): name = forms.CharField(min_length=4, max_length=10) pwd = forms.CharField(min_length=4) _pwd = forms.CharField(min_length=4) email = forms.EmailField() tel = forms.CharField() def reg_test(request): if request.method == "POST": form = UserForm(request.POST) # from表單的name屬性值應該與forms組件字段名稱一致 print(form) if form.is_valid(): print(form.cleaned_data) return HttpResponse("註冊成功") else: print(form.cleaned_data) # {'email': '123@qq.com', 'tel': 'a3456789'} print(form.errors) # <ul class="errorlist"><li>name<ul class="errorlist"><li>This fie print(type(form.errors)) # ErrorList print(form.errors.get('name')) # <ul class="errorlist"><li>This field is required.</li></ul> print(type(form.errors.get('name'))) # ErrorList print(form.errors.get('name')[0]) # This field is required. return HttpResponse("註冊失敗") return render(request, 'reg.html')
html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action="" method="post"> {% csrf_token %} <p>用戶名 <input type="text" name="user"></p> <p>密碼 <input type="password" name="pwd"></p> <p>確認密碼 <input type="password" name="_pwd"></p> <p>郵箱 <input type="text" name="email"></p> <p>手機號 <input type="text" name="tel"></p> <input type="submit" value="註冊"> </form> </body> </html>
注意點:
from表單的name屬性值應該與forms組件字段名稱一致
<tr><th><label for="id_name">Name:</label></th><td><ul class="errorlist"><li>This field is required.</li></ul><input type="text" name="name" maxlength="10" minlength="4" required id="id_name" /></td></tr> <tr><th><label for="id_pwd">Pwd:</label></th><td><ul class="errorlist"><li>Ensure this value has at least 4 characters (it has 3).</li></ul><input type="text" name="pwd" value="123" minlength="4" required id="id_pwd" /></td></tr> <tr><th><label for="id__pwd"> pwd:</label></th><td><ul class="errorlist"><li>Ensure this value has at least 4 characters (it has 3).</li></ul><input type="text" name="_pwd" value="123" minlength="4" required id="id__pwd" /></td></tr> <tr><th><label for="id_email">Email:</label></th><td><input type="email" name="email" value="123@qq.com" required id="id_email" /></td></tr> <tr><th><label for="id_tel">Tel:</label></th><td><input type="text" name="tel" value="a3456789" required id="id_tel" /></td></tr>
views
from django.shortcuts import render, HttpResponse from django import forms # 導入forms組件 # 定義校驗規則 class UserForm(forms.Form): name = forms.CharField(min_length=4, max_length=10) pwd = forms.CharField(min_length=4) r_pwd = forms.CharField(min_length=4) email = forms.EmailField() tel = forms.CharField() def reg_html(request): form = UserForm() return render(request, 'reg_html.html', locals())
reg.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h3>forms組件渲染方式1</h3> <form action="" method="post"> {% csrf_token %} <p>{{ form.name.label }} {{ form.name }}</p> <p>{{ form.pwd.label }} {{ form.pwd }}</p> <p>{{ form.r_pwd.label }} {{ form.r_pwd }}</p> <p>{{ form.email.label }} {{ form.email }}</p> <p>{{ form.tel.label }} {{ form.tel }}</p> <input type="submit" value="註冊"> </form> </body> </html>
原生標籤與渲染標籤的區別
views視圖
from django.shortcuts import render, HttpResponse # Create your views here. from django import forms # 導入forms組件 # 定義校驗規則 class UserForm(forms.Form): name = forms.CharField(min_length=4, max_length=10, label="用戶名") pwd = forms.CharField(min_length=4, label="密碼") r_pwd = forms.CharField(min_length=4, label="確認密碼") email = forms.EmailField(label="郵箱") tel = forms.CharField(label="電話") def reg_html(request): form = UserForm() return render(request, 'reg_html.html', locals())
html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h3>forms組件渲染方式2:推薦</h3> <form action="" method="post"> {% csrf_token %} {% for field in form %} <p><label for="">{{ field.label }}:</label>{{ field }}</p> {% endfor %} </form> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h3>forms組件渲染方式3 </h3> <form action="" method="post"> {% csrf_token %} {{ form.as_p }} <hr> {{ form.as_ul }} <hr> {{ form.as_table }} </form> </body> </html>
views視圖
from django.shortcuts import render, HttpResponse # Create your views here. from django import forms # 導入forms組件 # 定義校驗規則 class UserForm(forms.Form): name = forms.CharField(min_length=4, max_length=10, label="用戶名") pwd = forms.CharField(min_length=4, label="密碼") r_pwd = forms.CharField(min_length=4, label="確認密碼") email = forms.EmailField(label="郵箱") tel = forms.CharField(label="電話") def reg_html(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 render(request, 'reg_html.html', locals()) form = UserForm() return render(request, 'reg_html.html', locals())
html
novalidate 當提交表單時不對錶單數據(輸入)進行驗證
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h3>forms組件渲染方式1</h3> {# novalidate 當提交表單時不對錶單數據(輸入)進行驗證#} <form action="" method="post" novalidate> {% csrf_token %} <p>{{ form.name.label }} {{ form.name }} <span>{{ form.name.errors.0 }}</span></p> <p>{{ form.pwd.label }} {{ form.pwd }} <span>{{ form.pwd.errors.0 }}</span></p> <p>{{ form.r_pwd.label }} {{ form.r_pwd }} <span>{{ form.r_pwd.errors.0 }}</span></p> <p>{{ form.email.label }} {{ form.email }} <span>{{ form.email.errors.0 }}</span></p> <p>{{ form.tel.label }} {{ form.tel }} <span>{{ form.tel.errors.0 }}</span></p> <input type="submit" value="註冊"> </form> </body> </html>
forms組件 代碼
from django.shortcuts import render, HttpResponse # Create your views here. from django import forms # 導入forms組件 from django.forms import widgets # HTML Widget classes # 定義校驗規則 class UserForm(forms.Form): name = forms.CharField(min_length=4, max_length=10, label="用戶名", error_messages={'required': '該字段不能爲空', 'min_length': '不能少於4個字符'}, # widget=widgets.TextInput(), # 定製Html控件 widget=widgets.TextInput(attrs={'class': 'form-control'}), # html控件添加樣式 ) pwd = forms.CharField(min_length=4, label="密碼", # widget=widgets.PasswordInput(), # 定製Html控件 widget=widgets.PasswordInput(attrs={'class': 'form-control'}), error_messages={'required': '該字段不能爲空'}, ) r_pwd = forms.CharField(min_length=4, label="確認密碼", error_messages={'required': '該字段不能爲空'}, widget=widgets.PasswordInput(attrs={'class': 'form-control'}), ) email = forms.EmailField(label="郵箱", error_messages={'required': '該字段不能爲空', 'invalid': '格式錯誤'}, widget=widgets.EmailInput(attrs={'class': 'form-control'}) ) tel = forms.CharField(label="電話", error_messages={'required': '該字段不能爲空 '}, widget=widgets.TextInput(attrs={'class': 'form-control'}) ) def reg_html(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 render(request, 'reg_html.html', locals()) form = UserForm() return render(request, 'reg_html.html', locals())
加入bootstrap後的 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"> <style type="text/css"> span{ color: red; } </style> </head> <body> <div class="container"> <div class="row"> <div class="col-md-6 col-lg-offset-3"> <h3>forms組件渲染方式1</h3> {# novalidate 當提交表單時不對錶單數據(輸入)進行驗證#} <form action="" method="post" novalidate> {% csrf_token %} <p>{{ form.name.label }} {{ form.name }} <span>{{ form.name.errors.0 }}</span></p> <p>{{ form.pwd.label }} {{ form.pwd }} <span>{{ form.pwd.errors.0 }}</span></p> <p>{{ form.r_pwd.label }} {{ form.r_pwd }} <span>{{ form.r_pwd.errors.0 }}</span></p> <p>{{ form.email.label }} {{ form.email }} <span>{{ form.email.errors.0 }}</span></p> <p>{{ form.tel.label }} {{ form.tel }} <span>{{ form.tel.errors.0 }}</span></p> <input type="submit" value="註冊"> </form> </div> </div> </div> </body> </html>
models
from django.db import models 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)
froms組件,如何進行驗證錯誤?
from app01.models import UserInfo # 導入user表 from django.core.exceptions import ValidationError # 導入驗證錯誤 from django import forms # 導入forms組件 from django.forms import widgets # HTML Widget classes # 定義校驗規則 class UserForm(forms.Form): name = forms.CharField(min_length=4, max_length=10, label="用戶名", error_messages={'required': '該字段不能爲空', 'min_length': '不能少於4個字符'}, # widget=widgets.TextInput(), # 定製Html控件 widget=widgets.TextInput(attrs={'class': 'form-control'}), # html控件添加樣式 ) pwd = forms.CharField(min_length=4, label="密碼", # widget=widgets.PasswordInput(), # 定製Html控件 widget=widgets.PasswordInput(attrs={'class': 'form-control'}), error_messages={'required': '該字段不能爲空'}, ) r_pwd = forms.CharField(min_length=4, label="確認密碼", error_messages={'required': '該字段不能爲空'}, widget=widgets.PasswordInput(attrs={'class': 'form-control'}), ) email = forms.EmailField(label="郵箱", error_messages={'required': '該字段不能爲空', 'invalid': '格式錯誤'}, widget=widgets.EmailInput(attrs={'class': 'form-control'}) ) tel = forms.CharField(label="電話", error_messages={'required': '該字段不能爲空 '}, widget=widgets.TextInput(attrs={'class': 'form-control'}) ) # 驗證用戶名 def clean_name(self): val = self.cleaned_data.get("name") # 獲取清洗後的字段中的name ret = UserInfo.objects.filter(name=val) # 數據庫中的user if not ret: return ret else: raise ValidationError('該用戶已經註冊') # 驗證錯誤
forms組件源碼
vies視圖中
def reg_html(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 render(request, 'reg_html.html', locals()) form = UserForm() return render(request, 'reg_html.html', locals())
模板層:不變
<!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"> <style type="text/css"> span{ color: red; } </style> </head> <body> <div class="container"> <div class="row"> <div class="col-md-6 col-lg-offset-3"> <h3>forms組件渲染方式1</h3> {# novalidate 當提交表單時不對錶單數據(輸入)進行驗證#} <form action="" method="post" novalidate> {% csrf_token %} <p>{{ form.name.label }} {{ form.name }} <span>{{ form.name.errors.0 }}</span></p> <p>{{ form.pwd.label }} {{ form.pwd }} <span>{{ form.pwd.errors.0 }}</span></p> <p>{{ form.r_pwd.label }} {{ form.r_pwd }} <span>{{ form.r_pwd.errors.0 }}</span></p> <p>{{ form.email.label }} {{ form.email }} <span>{{ form.email.errors.0 }}</span></p> <p>{{ form.tel.label }} {{ form.tel }} <span>{{ form.tel.errors.0 }}</span></p> <input type="submit" value="註冊"> </form> </div> </div> </div> </body> </html>
_clean_fields 方法的源碼
def _clean_fields(self): for name, field in self.fields.items(): # {"name": name規則對象,"pwd": pwd規則對象...} # value_from_datadict() gets the data from the data dictionaries. # Each widget type knows how to retrieve its own data, because some # widgets split data over several HTML fields. if field.disabled: value = self.get_initial_for_field(field, name) else: value = field.widget.value_from_datadict(self.data, self.files, self.add_prefix(name)) try: if isinstance(field, FileField): initial = self.get_initial_for_field(field, name) value = field.clean(value, initial) else: value = field.clean(value) # 按照規則對象校驗傳遞進來的數據 self.cleaned_data[name] = value if hasattr(self, 'clean_%s' % name): value = getattr(self, 'clean_%s' % name)() self.cleaned_data[name] = value # 執行 def clean_name(self): except ValidationError as e: self.add_error(name, e)
from app01.models import UserInfo # 導入user表 from django.core.exceptions import ValidationError # 導入驗證錯誤 from django import forms # 導入forms組件 from django.forms import widgets # HTML Widget classes # 定義校驗規則 class UserForm(forms.Form): name = forms.CharField(min_length=4, max_length=10, label="用戶名", error_messages={'required': '該字段不能爲空', 'min_length': '不能少於4個字符'}, # widget=widgets.TextInput(), # 定製Html控件 widget=widgets.TextInput(attrs={'class': 'form-control'}), # html控件添加樣式 ) pwd = forms.CharField(min_length=4, label="密碼", # widget=widgets.PasswordInput(), # 定製Html控件 widget=widgets.PasswordInput(attrs={'class': 'form-control'}), error_messages={'required': '該字段不能爲空'}, ) r_pwd = forms.CharField(min_length=4, label="確認密碼", error_messages={'required': '該字段不能爲空'}, widget=widgets.PasswordInput(attrs={'class': 'form-control'}), ) email = forms.EmailField(label="郵箱", error_messages={'required': '該字段不能爲空', 'invalid': '格式錯誤'}, widget=widgets.EmailInput(attrs={'class': 'form-control'}) ) tel = forms.CharField(label="電話", error_messages={'required': '該字段不能爲空 '}, widget=widgets.TextInput(attrs={'class': 'form-control'}) ) # 驗證用戶名 def clean_name(self): val = self.cleaned_data.get("name") # 獲取清洗後的字段中的name ret = UserInfo.objects.filter(name=val) # 數據庫中的user if not ret: return ret else: raise ValidationError('該用戶已經註冊') # 驗證錯誤 # 驗證手機號 def clean_tel(self): val = self.cleaned_data.get("tel") if len(val) == 11: return val else: raise ValidationError("手機號格式錯誤")
froms組件繼承的是BaseFrom類,因此能夠直接覆蓋父類的clean方法,進行全局鉤子校驗
views視圖
from django.shortcuts import render, HttpResponse from app01.models import UserInfo # 導入user表 from django.core.exceptions import ValidationError # 導入驗證錯誤 from django import forms # 導入forms組件 from django.forms import widgets # HTML Widget classes # 定義校驗規則 class UserForm(forms.Form): name = forms.CharField(min_length=4, max_length=10, label="用戶名", error_messages={'required': '該字段不能爲空', 'min_length': '不能少於4個字符'}, # widget=widgets.TextInput(), # 定製Html控件 widget=widgets.TextInput(attrs={'class': 'form-control'}), # html控件添加樣式 ) pwd = forms.CharField(min_length=4, label="密碼", # widget=widgets.PasswordInput(), # 定製Html控件 widget=widgets.PasswordInput(attrs={'class': 'form-control'}), error_messages={'required': '該字段不能爲空'}, ) r_pwd = forms.CharField(min_length=4, label="確認密碼", error_messages={'required': '該字段不能爲空'}, widget=widgets.PasswordInput(attrs={'class': 'form-control'}), ) email = forms.EmailField(label="郵箱", error_messages={'required': '該字段不能爲空', 'invalid': '格式錯誤'}, widget=widgets.EmailInput(attrs={'class': 'form-control'}) ) tel = forms.CharField(label="電話", error_messages={'required': '該字段不能爲空 '}, widget=widgets.TextInput(attrs={'class': 'form-control'}) ) # 直接覆蓋父類的clean方法, 全局鉤子 def clean(self): pwd = self.cleaned_data.get("pwd") r_pwd = self.cleaned_data.get("r_pwd") if pwd == r_pwd: return self.cleaned_data else: raise ValidationError("兩次密碼不一致") def reg_html(request): if request.method == 'POST': form = UserForm(request.POST) if form.is_valid(): print(form.cleaned_data) # {"name": "alex", "pwd": "123",...} else: print(form.cleaned_data) # # 全部清洗的字段以及對應的值 print(form.errors) # ErrorDict: {"校驗錯誤的字段":["錯誤信息"]} print(form.errors.get('name')) # ErrorList {'錯誤信息',} # 獲取全局鉤子的error print("error:", form.errors.get("__all__")[0]) errors = form.errors.get("__all__") return render(request, 'reg_html.html', locals()) form = UserForm() return render(request, 'reg_html.html', locals())
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"> <style type="text/css"> span{ color: red; } </style> </head> <body> <div class="container"> <div class="row"> <div class="col-md-6 col-lg-offset-3"> <h3>forms組件渲染方式1</h3> {# novalidate 當提交表單時不對錶單數據(輸入)進行驗證#} <form action="" method="post" novalidate> {% csrf_token %} <p>{{ form.name.label }} {{ form.name }} <span>{{ form.name.errors.0 }}</span></p> <p>{{ form.pwd.label }} {{ form.pwd }} <span>{{ form.pwd.errors.0 }}</span></p> {# <p>{{ form.r_pwd.label }} {{ form.r_pwd }} <span>{{ form.r_pwd.errors.0 }}</span></p> 局部鉤子錯誤#} <p>{{ form.r_pwd.label }} {{ form.r_pwd }} <span class="pull-right error">{{ errors.0 }}</span></p> <p>{{ form.email.label }} {{ form.email }} <span>{{ form.email.errors.0 }}</span></p> <p>{{ form.tel.label }} {{ form.tel }} <span>{{ form.tel.errors.0 }}</span></p> <input type="submit" value="註冊"> </form> </div> </div> </div> </body> </html>
重點
# 接收全局鉤子error errors.0 # bootstarp樣式 <span class="pull-right error"> <p>{{ form.r_pwd.label }} {{ form.r_pwd }} <span class="pull-right error">{{ errors.0 }}</span></p>
# 每一個字段校驗完,在走全局方法 好比,先判斷密碼是否正確,符合規則再判斷,兩次密碼是否一致
若是沒有pwd傳入進來的話,
# 直接覆蓋父類的clean方法, 全局鉤子 def clean(self): pwd = self.cleaned_data.get("pwd") r_pwd = self.cleaned_data.get("r_pwd") # 先判斷是否接受到pwd,r_pwd的值 if pwd and r_pwd: if pwd == r_pwd: return self.cleaned_data else: raise ValidationError("兩次密碼不一致") else: return self.cleaned_data
form.is_valid def is_valid(self): """Return True if the form has no errors, or False otherwise.""" return self.is_bound and not self.errors def errors(self): """Return an ErrorDict for the data provided for the form.""" if self._errors is None: self.full_clean() return self._errors def full_clean(self): """ Clean all of self.data and populate self._errors and self.cleaned_data. """ self._errors = ErrorDict() if not self.is_bound: # Stop further processing. return self.cleaned_data = {} # If the form is permitted to be empty, and none of the form data has # changed from the initial data, short circuit any validation. if self.empty_permitted and not self.has_changed(): return self._clean_fields() # 校驗每個字段 self._clean_form() # 校驗所有字段 self._post_clean()
# 局部鉤子 def _clean_fields(self): for name, field in self.fields.items(): # 校驗每個字段 # value_from_datadict() gets the data from the data dictionaries. # Each widget type knows how to retrieve its own data, because some # widgets split data over several HTML fields. if field.disabled: value = self.get_initial_for_field(field, name) else: value = field.widget.value_from_datadict(self.data, self.files, self.add_prefix(name)) try: if isinstance(field, FileField): initial = self.get_initial_for_field(field, name) value = field.clean(value, initial) else: value = field.clean(value) self.cleaned_data[name] = value if hasattr(self, 'clean_%s' % name): value = getattr(self, 'clean_%s' % name)() self.cleaned_data[name] = value except ValidationError as e: self.add_error(name, e)
# 全局鉤子調用順序 def _clean_form(self): try: cleaned_data = self.clean() # 全局鉤子 except ValidationError as e: self.add_error(None, e) else: if cleaned_data is not None: self.cleaned_data = cleaned_data def clean(self): """ Hook for doing any extra form-wide cleaning after Field.clean() has been called on every field. Any ValidationError raised by this method will not be associated with a particular field; it will have a special-case association with the field named '__all__'. """ return self.cleaned_data @html_safe class BaseForm: """ The main implementation of all the Form logic. Note that this class is different than Form. See the comments by the Form class for more info. Any improvements to the form API should be made to this class, not to the Form class. """ def clean(self): pass
myforms.py 組件代碼
from app01.models import UserInfo # 導入user表 from django.core.exceptions import ValidationError # 導入驗證錯誤 from django import forms # 導入forms組件 from django.forms import widgets # HTML Widget classes # 定義校驗規則 class UserForm(forms.Form): name = forms.CharField(min_length=4, max_length=10, label="用戶名", error_messages={'required': '該字段不能爲空', 'min_length': '不能少於4個字符'}, # widget=widgets.TextInput(), # 定製Html控件 widget=widgets.TextInput(attrs={'class': 'form-control'}), # html控件添加樣式 ) pwd = forms.CharField(min_length=4, label="密碼", # widget=widgets.PasswordInput(), # 定製Html控件 widget=widgets.PasswordInput(attrs={'class': 'form-control'}), error_messages={'required': '該字段不能爲空'}, ) r_pwd = forms.CharField(min_length=4, label="確認密碼", error_messages={'required': '該字段不能爲空'}, widget=widgets.PasswordInput(attrs={'class': 'form-control'}), ) email = forms.EmailField(label="郵箱", error_messages={'required': '該字段不能爲空', 'invalid': '格式錯誤'}, widget=widgets.EmailInput(attrs={'class': 'form-control'}) ) tel = forms.CharField(label="電話", error_messages={'required': '該字段不能爲空 '}, widget=widgets.TextInput(attrs={'class': 'form-control'}) ) # 驗證用戶名 def clean_name(self): val = self.cleaned_data.get("name") # 獲取清洗後的字段中的name ret = UserInfo.objects.filter(name=val) # 數據庫中的user if not ret: return ret else: raise ValidationError('該用戶已經註冊') # 驗證錯誤 # 驗證手機號 def clean_tel(self): val = self.cleaned_data.get("tel") if len(val) == 11: return val else: raise ValidationError("手機號格式錯誤") # 直接覆蓋父類的clean方法, 全局鉤子 def clean(self): pwd = self.cleaned_data.get("pwd") r_pwd = self.cleaned_data.get("r_pwd") # 先判斷是否接受到pwd,r_pwd的值 if pwd and r_pwd: if pwd == r_pwd: return self.cleaned_data else: raise ValidationError("兩次密碼不一致") else: return self.cleaned_data
url
from django.urls import path, re_path, include from app01 import views urlpatterns = [ re_path(r'reg_html/$', views.reg_html, name='reg_html'), ]
views視圖代碼
from django.shortcuts import render from app01.myforms import * def reg_html(request): if request.method == 'POST': form = UserForm(request.POST) if form.is_valid(): print(form.cleaned_data) # {"name": "alex", "pwd": "123",...} else: print(form.cleaned_data) # # 全部清洗的字段以及對應的值 print(form.errors) # ErrorDict: {"校驗錯誤的字段":["錯誤信息"]} print(form.errors.get('name')) # ErrorList {'錯誤信息',} # 獲取全局鉤子的error # print("error:", form.errors.get("__all__")[0]) errors = form.errors.get("__all__") return render(request, 'reg_html.html', locals()) form = UserForm() return render(request, 'reg_html.html', locals())
模板層
<!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"> <style type="text/css"> span{ color: red; } </style> </head> <body> <div class="container"> <div class="row"> <div class="col-md-6 col-lg-offset-3"> <h3>forms組件渲染方式1</h3> {# novalidate 當提交表單時不對錶單數據(輸入)進行驗證#} <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.label }} {{ form.r_pwd }} <span>{{ form.r_pwd.errors.0 }}</span></p> #} {# 全局鉤子錯誤#}<p>{{ form.r_pwd.label }} {{ form.r_pwd }} <span class="pull-right error">{{ errors.0 }}</span></p> <p>{{ form.email.label }} {{ form.email }} <span class="pull-right error">{{ form.email.errors.0 }}</span></p> <p>{{ form.tel.label }} {{ form.tel }} <span class="pull-right error">{{ form.tel.errors.0 }}</span></p> <input type="submit" value="註冊"> </form> </div> </div> </div> </body> </html>