前言
Django中完成表單驗證,常用的有兩種方法:
一種是通過HTML + JS + Ajax實現。
另一種是通過Django自身的forms模塊來生成相應個HTML標簽來完成表單驗證。這是本節着重講的地方
第一種方法:html + ajax實現基本的login頁面

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title></title> <style> .error-msg{ color: red; } </style> </head> <body> <div> <div> <input type="text" name="user" /> </div> <div> <input type="password" name="pwd" /> </div> <div> <input type="text" name="num" /> </div> <div> <input type="text" name="phone" /> </div> <input type="button" value="提交" onclick="DoSubmit();" /> </div> <script src="/static/jquery-2.1.4.min.js"></script> <script> function DoSubmit(){ var input_dict = {}; $('input').each(function(){ var v = $(this).val(); var n = $(this).attr('name'); input_dict[n] = v; }); console.log(input_dict); $('.error-msg').remove(); $.ajax({ url: '/login/', type: 'POST', data: input_dict, dataType: 'json', success: function (result) { if(result.status){ location.href = '/index/'; }else{ $.each(result.message, function (k,v) { console.log(k,v[0].message); // <span class="error-msg">錯誤信息</span> var tag = document.createElement('span'); tag.className = 'error-msg'; tag.innerText = v[0].message; // input[name="user"] $('input[name="' + k + '"]').after(tag); }) } }, error: function () { } }) } </script> </body> </html>

from django.shortcuts import render,HttpResponse # Create your views here. from django import forms from django.core.exceptions import ValidationError import re 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 LoginForm(forms.Form): user = forms.CharField(required=True, error_messages={'required': '用戶名不能為空.'}) pwd = forms.CharField(required=True, min_length=6, max_length=10, error_messages={'required': '密碼不能為空.', 'min_length': "至少6位"}) num = forms.IntegerField(error_messages={'required': '數字不能空.','invalid': '必須輸入數字'}) phone = forms.CharField(validators=[mobile_validate, ],) import json def login(request): if request.method == 'POST': result = {'status': False, 'message': None} obj = LoginForm(request.POST) ret = obj.is_valid() if ret: print(obj.clean()) result['status'] = True else: from django.forms.utils import ErrorDict #print(type(obj.errors),obj.errors.as_json()) error_str = obj.errors.as_json() result['message'] = json.loads(error_str) return HttpResponse(json.dumps(result)) return render(request, 'login.html')
這里邊views中,已經用到了django自帶的forms模塊。在不用這個模塊之前,我們對於用戶輸入進行判斷,需要一堆的if..if...if語句來進行,但是用了這個模塊之后,僅需要在定義好LoginForm類中每個字段的屬性后,通過obj = LoginForm(request.POST)和ret = obj.is_valid()兩步,就可以完成對於用戶輸入信息的驗證。ret會返回驗證是否全部通過。全部通過則為True,只要有一條表單信息驗證不通過,則為False。
這里需要關注的知識點是:obj.clean() 是輸出用戶post的正確信息,是一個dict,obj.errors是輸出用戶post的錯誤信息,是一個通過ul li顯示的信息,這樣不方便查看。可以通過obj.errors.as_json()來將錯誤信息以json形式展示,用error_str = obj.errors.as_json() 和 result['message'] = json.loads(error_str)來完成錯誤信息收集。
另外定義表單驗證規則LoginForm類時,字段名需要等於html中name值
補充知識點:在定義的LoginForm中,定義的pwd字段是這樣定義的
pwd = forms.CharField(required=True, min_length=6, max_length=10, error_messages={'required': '密碼不能為空.', 'min_length': "至少6位"})
其中error_messages屬性是用來定義錯誤信息的展示的。解釋為:如果required驗證不通過,則提示'密碼不能為空',min_length驗證不通過,則錯誤信息為'至少6位'。擴展'invalid': '必須輸入數字'
第二種方法:利用forms模塊生成html標簽
forms能解決的2個問題:
問題1: 如果使用html自帶的form標簽來進行提交,如果提交的數據有錯誤,會清空表單中的全部數據,如果表單項較多,對用戶非常不友好。那么forms模塊就能解決這個問題。
問題2: 使用html的form標簽提交數據,需要input標簽的name屬性必須和定義的class類的屬性一致。而使用django forms模塊,則不需要考慮這個問題。
廢話不多說,直接貼代碼
前端代碼

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title></title> <style> .error-msg{ color: red; } </style> </head> <body> <form action="/login/" method="POST"> <div> <div> {{ obj1.user }} {% if obj1.errors.user %} <span class="error-msg">{{ obj1.errors.user.0 }}</span> {% endif %} </div> <div> {{ obj1.pwd }} <span class="error-msg">{{ obj1.errors.pwd.0 }}</span> </div> <div> {{ obj1.num }} <span class="error-msg">{{ obj1.errors.num.0 }}</span> </div> <div> {{ obj1.phone }} <span class="error-msg">{{ obj1.errors.phone.0 }}</span> </div> <div> {{ obj1.test }} <span class="error-msg">{{ obj1.errors.test.0 }}</span> </div> <input type="submit" value="提交" /> </div> </form> </body> </html>
后端代碼

from django.shortcuts import render,HttpResponse,redirect # Create your views here. from django import forms from django.core.exceptions import ValidationError import re 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 LoginForm(forms.Form): user = forms.CharField(required=True, error_messages={'required': '用戶名不能為空.'}) pwd = forms.CharField(required=True, min_length=6, max_length=10, error_messages={'required': '密碼不能為空.', 'min_length': "至少6位"}) num = forms.IntegerField(error_messages={'required': '數字不能空.','invalid': '必須輸入數字'}) phone = forms.CharField(validators=[mobile_validate, ],) #test = forms.CharField(widget=forms.Textarea(attrs={'class': 'c1'})) test_choices = ( (0, '上海'), (1, '背景'), ) test = forms.IntegerField(widget=forms.Select(choices=test_choices)) def login(request): if request.POST: objPost = LoginForm(request.POST) ret = objPost.is_valid() if ret: print(objPost.clean()) else: from django.forms.utils import ErrorDict #print(type(obj.errors),obj.errors.as_json()) # obj1.errors pass return render(request, 'login.html',{'obj1': objPost}) else: objGet = LoginForm() return render(request, 'login.html',{'obj1': objGet})

from django.conf.urls import url from app01 import views urlpatterns = [ url(r'^login/', views.login), ]
知識點:如何生成自定義的標簽類型
forms默認幫我們生成的是INPUT標簽,同時也支持生成其他標簽。在源代碼中,可以看到支持很多的Field類型
上邊的一堆類可以看出,繼承Field的類,可以用作生成標簽,這些類都寫在fields.py文件中。而forms.IntegerField(widget=forms.Select(choices=test_choices)中的widget字段中的類,都需要繼承自Widget才可以,這些類都寫在widgets.py中。
比如,如果生成下拉框可以這么寫:
test_choices = ( (0, '上海'), (1, '背景'), ) test = forms.IntegerField(widget=forms.Select(choices=test_choices))
知識點:如何給生成的標簽自定義屬性
test = forms.CharField(widget=forms.Textarea(attrs={'class': 'c1'}))