Python菜鳥之路:Django 表單驗證


前言

  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>
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代碼

  這里邊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>
login.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})
views.py
from django.conf.urls import url

from app01 import views

urlpatterns = [

    url(r'^login/', views.login),

]
urls.py

知識點:如何生成自定義的標簽類型

  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'}))

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM