回憶一下Form表單驗證的邏輯:
前端有若干個input輸入框,將用戶輸入內容,以字典傳遞給后端。
后端預先存在一個Form表單驗證的基類,封裝了一個檢測用戶輸入是否全部通過的方法。該方法會先定義好錯誤信息的字典,並會遍歷類的所有屬性(對應前端待驗證的輸入域),調用各自的驗證方法,將錯誤信息(兩類,必要與否以及格式正確與否)存入字典,並得出最終的驗證結果。在使用時,需要定義繼承自Form基類不同的Form類,以對應有着不同輸入域的Form表單。在拿到前端給的字典前,要先初始化自定義From類,直接執行封裝好的整體驗證方法,拿到結果后就可以拋給前端了。
Django中Form表單驗證涉及到的知識:
1.Django中的ErrorDcit類如何封裝了錯誤信息
# project/app01/forms.py from django import forms # 繼承自Django的Form類 # 內部以字段形式定義驗證域 class MyForm(forms.Form): user = forms.CharField() pwd = forms.CharField()
# project/app01/views.py def form(request): from app01.forms import MyForm if request.method == 'POST': f = MyForm(request.POST) ret = f.is_valid() # bool data = f.cleaned_data # {'user': 'asd', 'pwd': 'asd'} errors = f.errors # ErrorDict,打印時因為__str__方法,會顯示位ul標簽的形式 print(errors.get('user', None)[0] if errors.get('user', None) else None) # ErrorList,以索引取出第一條錯誤信息 return render(request, "form.html", {"errors": f.errors}) return render(request, "form.html")
# project/templates/forms.html <form action="/form/" method="post"> <div> 用戶名:<input type="text" name="user"/> </div> <div> 密碼:<input type="password" name="pwd"/> </div> <div> <input type="submit" value="提交"/> </div> {{ errors }} <div></div>
2.拋給前端的ErrorDcit及使用模板語言漂合理展示
展示錯誤信息的前端布局
通過返回Form類和模板語言在前端動態生成input標簽
# project/app01/views.py def form(request): from app01.forms import MyForm empty_form = MyForm() if request.method == 'POST': f = MyForm(request.POST) if f.is_valid(): print(f.cleaned_data) # 這里只是為了使得正確提交后不至於讓input消失,實際壞境中這里應該是用戶信息驗證 return render(request, "form.html", {'myform': empty_form}) return render(request, "form.html", {"errors": f.errors, "myform": f}) else: return render(request, "form.html", {'myform': empty_form})
# project/templates/forms.html <head> <meta charset="UTF-8"> <title>Title</title> <style> .input-group{ padding: 15px; } .input-group input{ width: 200px; } .input-group span{ display: inline-block; position: relative; border: 1px solid red; top: 25px; left: -211px; } </style> </head> <body> <form action="/form/" method="post"> <div class="input-group"> <div style="float:left;width:70px;">用戶名:</div> {{ myform.user }} {% if errors.user.0 %} <span>{{ errors.user.0 }}</span> {% endif %} </div> <div class="input-group"> <div style="float:left;width:70px;">密碼:</div> {{ myform.pwd }} {% if errors.pwd.0 %} <span>{{ errors.pwd.0 }}</span> {% endif %} </div> <div> <input style="float:left;margin-left:15px;" type="submit" value="提交"/> </div> </form>
4.django.forms中的CharField參數
(required, min/max_length,error_messages,forms.widget)
不重啟服務時數據庫數據動態更新到前端(靜態字段的特點)
field不合需求時自定義驗證規則(validators參數)
# project/app01/forms.py from django import forms from app01 import models def mobile_validate(value): import re mobile_re = re.compile("^(13[0-9]|14[579]|15[0-3,5-9]|1 6[6]|17[0135678]|18[0-9]|19[89])\\d{8}$") if not mobile_re.match(value): print('123123') raise forms.ValidationError('手機號碼格式不對哦') class MyForm(forms.Form): def __init__(self, *args, **kwargs): super(MyForm, self).__init__(*args, **kwargs) self.fields['book_type'] = forms.CharField( widget=forms.Select(choices=models.BookType.objects.values_list('id', 'caption')) ) user = forms.CharField(min_length=4, max_length=10, widget=forms.TextInput) pwd = forms.CharField(error_messages={'required': '為什么不輸入密碼??'}) email = forms.EmailField(error_messages={'required': '郵箱還沒輸入哦', 'invalid': '郵箱格式錯誤'}) # book_type_choices = ( # (0, '小說'), value # (1, '科普'), innerText # ) # 元組內有元組 # 從數據庫獲得數據 # 注意這里filed都是靜態字段 # 類的靜態字段只創建一次以后不會再修改,新的對象都會使用同一份數據 # 所以MyForm這里的靜態字段只會執行一次 # 加入數據庫中的數據更新了,服務器不重啟的話,這里從數據庫取來的值是不會變的 # 因此將該字段寫入類的初始化方法里,不要忘了執行父類的初始化方法哦 # book_type_choices = models.BookType.objects.values_list('id', 'caption') # book_type = forms.CharField( # widget=forms.Select(choices=book_type_choices) # ) comment = forms.CharField( widget=forms.Textarea(attrs={'style': 'border:1px solid red;'}) ) # 可以為生成的標簽添加屬性 mobile = forms.CharField( validators=[mobile_validate, ], error_messages={'required': '手機號不填不行'}, widget=forms.TextInput )
<div class="input-group"> <div style="float:left;width:70px;">用戶名:</div> {{ myform.user }} {% if errors.user.0 %} <span>{{ errors.user.0 }}</span> {% endif %} </div> <div class="input-group"> <div style="float:left;width:70px;">密碼:</div> {{ myform.pwd }} {% if errors.pwd.0 %} <span>{{ errors.pwd.0 }}</span> {% endif %} </div> <div class="input-group"> <div style="float:left;width:70px;">郵箱:</div> {{ myform.email }} {% if errors.email.0 %} <span>{{ errors.email.0 }}</span> {% endif %} // 以下都是上面input-group標簽的重復,只是field不同而已,不再細說
碎碎念:
中間給render傳入兩個字典,一直調試不出問題,費時頗久,下次留心。
