views.pyhtml
from django.shortcuts import render, HttpResponse # Create your views here. from django import forms from django.forms import widgets class UserForm(forms.Form): name = forms.CharField(min_length=4,label='用戶名') # 必須用required 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(request): if request.method == 'POST': # form = UserForm({'name': 'ed', 'email': '123@qq.com'}) # 加多少個鍵值都無所謂,只要能匹配全Form裏的字段就會返回True # print(form.is_valid()) # 返回布爾值 form = UserForm(request.POST) # form表單的name屬性值應該與forms組件字段名稱一致 if form.is_valid(): print(form.changed_data) # 存的是經過校驗的字典 else: print(form.cleaned_data) # {正確的鍵值,"email":"123@11.com"} print(form.errors) # {"name":["insure this value has at least 4 characters]} print(type(form.errors)) # ErrorDict print(form.errors.get('name')) print(type(form.errors.get('name'))) # ErrorList print(form.errors.get('name')[0]) # This field is required. ''' if 全部字段校驗成功,則form.cleaned_data:{'name': 'edward', 'email': '123@qq.com'} ''' return render(request, 'register.html', locals()) form = UserForm() # get請求的form,渲染form組件用 return render(request, 'register.html', locals())
html前端
<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="r_pwd"></p> <p>郵箱:<input type="email" name="email"></p> <p>手機號:<input type="text" name="tel"></p> <input type="submit" value="提交"> </form>
<h3>form組件渲染方式1</h3> <form action="" method="post"> {% 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> <hr> <h3>form組件渲染方式2</h3> <form action="" method="post"> {% csrf_token %} {% for filed in form %} <p> <label for="">{{ filed.label }}</label> {{ filed }} </p> {% endfor %} <input type="submit" value="提交"> </form> <hr> <h3>form組件渲染方式3 --- 不建議使用這種方式,由於它只能固定放那麼幾個標籤,缺少靈活性,之後改動麻煩</h3> <form action="" method="post"> {% csrf_token %} {{ form.as_p }} <input type="submit" value="提交"> </form>
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'}), 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.TextInput(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') ret = UserInfo.objects.filter(name=val) if not ret: return val else: raise ValidationError('該用戶已註冊!') def clean_tel(self): val = self.cleaned_data.get('tel') ret = UserInfo.objects.filter(tel=val) if len(ret) == 11: return val else: raise ValidationError('手機號格式錯誤') # 源碼 def _clean_fields(self): 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)
爲了解耦,新建一個myforms.py的文件,把有關forms的代碼都放在這裏面。django
# 全局鉤子 # 走完全部的校驗才走clean def clean(self): # 走完全部的校驗才走clean pwd = self.cleaned_data.get('pwd') r_pwd = self.cleaned_data.get('r_pwd') # 都知足不低於4個字符這個條件後才驗證密碼是否一致 if pwd and r_pwd: if pwd == r_pwd: return self.cleaned_data else: raise ValidationError('兩次密碼不一致') else: return self.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 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 # 全局鉤子在前端沒有顯示,要在處理post請求的代碼裏給錯誤信息一個變量並傳到前端 errors = form.errors.get('__all__') # 當兩次密碼不一致時,在前端顯示這個錯誤 <p> {{ form.r_pwd.label }}:{{ form.r_pwd }} <span class="pull-right error">{{ form.r_pwd.errors.0 }}</span> <span class="pull-right error">{{ errors.0 }}</span> </p>