django之form表單驗證

form組件的校驗功能

 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>

 

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>
相關文章
相關標籤/搜索