1. 程式人生 > >Django 學習之路:Django之強大的Form功能

Django 學習之路:Django之強大的Form功能

Django之強大的Form功能

Form Form的驗證思路

前端:form表單

後臺:建立form類,當請求到來時,先匹配,匹配出正確和錯誤資訊。

Django的Form驗證例項: 建立project,進行基礎配置檔案配置 在這裡插入圖片描述

STATIC_URL = '/static/'
STATICFILES_DIRS = (
    os.path.join(BASE_DIR,"static"),
)
MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    # 'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

init.py

import pymysql
pymysql.install_as_MySQLdb()
from django.conf.urls import url
from django.contrib import admin
from app01.views import account

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^form1/', account.form1),
    # url(r'^test/', account.test),
]
from django.shortcuts import render,HttpResponse
from app01.forms import Form1

def form1(request):
    if request.method=="POST":  #這裡POST一定要大寫
        #通常獲取請求資訊
        #request.POST.get("user",None)
        #request.POST.get("pwd",None)
        #獲取請求內容,做驗證
        f = Form1(request.POST)  #request.POST:將接收到的資料通過Form1驗證
        if f.is_valid():  #驗證請求的內容和Form1裡面的是否驗證通過。通過是True,否則False。
            print(f.cleaned_data)  #cleaned_data型別是字典,裡面是提交成功後的資訊
        else:  #錯誤資訊包含是否為空,或者符合正則表示式的規則
            print(type(f.errors),f.errors)  #errors型別是ErrorDict,裡面是ul,li標籤
            return render(request,"account/form1.html",{"error":f.errors})
    return render(request,"account/form1.html")

html:

<body>
{#{{ error }}接收後臺返回的錯誤資訊封裝在ul,li標籤裡面:#}
    {{ error }}
    <form action="/form1/" method="POST">
        <div>
            <input type="text" name="user" />
        </div>
        <div>
            <input type="text" name="pwd" />
        </div>
        <div>
            <input type="submit" value="提交" />
        </div>
    </form>
</body>
from django import forms

class Form1(forms.Form):
    user = forms.CharField()
    pwd = forms.CharField()

訪問頁面: 在這裡插入圖片描述 沒有輸入內容後提交,通過模板語言展示了錯誤資訊 在這裡插入圖片描述 Django強大之form驗證時不用自定義錯誤資訊就可以返回錯誤資訊到前端以標籤方式展現。

.is_valid():返回True或者False

.cleaned_data:通過驗證後的資料

errors: .error.get(“user”,None)error封裝所有的錯誤資訊,如果沒有獲取到,預設為None。

如:

.error.get[“pwd”]直接獲取到ul、li。

如: 在這裡插入圖片描述

from django import forms

class Form1(forms.Form):
    user = forms.CharField()
    pwd = forms.CharField()

HTML:

 <form action="/form1/" method="POST">
        <div class="input-group">
            {#接收後臺傳過來的form物件,自動生成input標籤#}
            {{ form.user }}
            {#從後臺傳過來的error是字典,直接{{ error.user.0 }}呈現錯誤資訊#}
       {#如果後臺返回了錯誤資訊,將錯誤資訊放入span標籤,在頁面顯示,否則不顯示#}
            {% if error.user.0 %}
            <span>{{ error.user.0 }}</span>
            {% endif %}
        </div>
        <div class="input-group">
            {{ form.pwd }}
            {% if error.pwd.0 %}
            <span>{{ error.pwd.0 }}</span>
            {% endif %}
        </div>
        <div>
            <input type="submit" value="提交" />
        </div>
    </form>
def form1(request):
    if request.method == "POST":
        f = Form1(request.POST)
        if f.is_valid():
            print(f.cleaned_data)
        else:
            return render(request,"account/form1.html",{"error":f.errors,"form":f})
    else:
        # 如果不是post提交資料,就不傳引數建立物件,並將物件返回給前臺,直接生成input標籤,內容為空
        f = Form1()
        return render(request,"account/form1.html",{"form":f})
    return render(request,"account/form1.html")

注意: 在這裡插入圖片描述 頁面展示:

在這裡插入圖片描述

注:這裡的input標籤是後端返回form物件到前端通過{{ form.xxx }}所建立的

更強大的功能:

forms裡面的欄位:

required:是否可以為空。required=True 不可以為空,required=False 可以為空
max_length=4 最多4個值,超過不會顯示
min_length=2 至少兩個值,少於兩個會返回提示資訊
error_messages={'required': '郵箱不能為空', 'invalid': '郵箱格式錯誤'}  自定義錯誤資訊,invalid 是格式錯誤
widget=forms.TextInput(attrs={'class': 'c1'}) 給自動生成的input標籤自定義class屬性
widget=forms.Textarea()  生成Textarea標籤。widget預設生成input標籤

實戰:

from django.db import models

# Create your models here.
class Author(models.Model):
    """
    作者
    """
    name = models.CharField(max_length=100)
    age = models.IntegerField()

class BookType(models.Model):
    """
    圖書型別
    """
    caption = models.CharField(max_length=64)

class Book(models.Model):
    """
    圖書
    """
    name = models.CharField(max_length=64)
    pages = models.IntegerField()
    price = models.DecimalField(max_digits=10,decimal_places=2)
    pubdate = models.DateField()

    authors = models.ManyToManyField(Author)
    book_type = models.ForeignKey(BookType)
from django import forms
from app01 import models

class Form1(forms.Form):
    user = forms.CharField(
        widget=forms.TextInput(attrs={'class': 'c1'}),
        error_messages={'required': '使用者名稱不能為空'}, )
    pwd = forms.CharField(max_length=4, min_length=2,required=True)
    email = forms.EmailField(error_messages={'required': '郵箱不能為空', 'invalid': '郵箱格式錯誤'})

    memo = forms.CharField(
        widget=forms.Textarea()
    )
    #直接寫資料
    # user_type_choice = (
    #     (0, '普通使用者'),
    #     (1, '高階使用者'),
    # )
    #通過BookType表查詢資訊,values_list拿到的是元組。id作為value顯示,caption作為text在頁面顯示
    # user_type_choice = models.BookType.objects.values_list('id', 'caption')
    # book_type = forms.CharField(
    #     widget=forms.widgets.Select(choices=user_type_choice, attrs={'class': "form-control"}))

    
    #寫上以下程式碼就不用擔心資料庫添加了資料而不能及時獲取了
    def __init__(self, *args, **kwargs):
        #每次建立Form1物件時執行init方法
        super(Form1, self).__init__(*args, **kwargs)

        self.fields['book_type'] = forms.CharField(
            widget=forms.widgets.Select(choices=models.BookType.objects.values_list('id', 'caption'),
                                        attrs={'class': "form-control"}))

HTML:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        .input-group{
            position: relative;
            padding: 20px;
            width: 250px;
        }
        .input-group input{
            width: 200px;
            display: inline-block;
        }
        .inline-group span{
            display: inline-block;
            position: absolute;
            height: 12px;
            font-size: 8px;
            border: 1px solid red;
            background-color: coral;
            color: white;
            top: 41px;
            left: 20px;
            width: 202px;
        }
    </style>
</head>
<body>
    <form action="/form1/" method="POST">
        <div class="input-group">
{#            接收後臺傳過來的form物件,自動生成input標籤#}
            {{ form.user }}
{#            從後臺傳過來的error是字典,直接{{ error.user.0 }}呈現錯誤資訊#}
{#            如果後臺返回了錯誤資訊,將錯誤資訊放入span標籤,在頁面顯示,否則不顯示#}
            {% if error.user.0 %}
            <span>{{ error.user.0 }}</span>
            {% endif %}
        </div>
        <div class="input-group">
            {{ form.pwd }}
            {% if error.pwd.0 %}
            <span>{{ error.pwd.0 }}</span>
            {% endif %}
        </div>
        <div class="input-group">
            {{ form.email }}
            {% if error.email.0 %}
            <span>{{ error.email.0 }}</span>
            {% endif %}
        </div>
         <div class="input-group">
            {{ form.memo }}
            {% if error.memo.0 %}
            <span>{{ error.memo.0 }}</span>
            {% endif %}
        </div>
             <div class="input-group">
            {{ form.book_type }}
            {% if error.book_type.0 %}
            <span>{{ error.book_type.0 }}</span>
            {% endif %}
        </div>

        <div>
            <input type="submit" value="提交" />
        </div>
    </form>

</body>
</html>
from django.shortcuts import render,HttpResponse
from app01.forms import Form1
from app01.models import *


# def test(req):
#     BookType.objects.create(caption='技術')
#     BookType.objects.create(caption='文學')
#     BookType.objects.create(caption='動漫')
#     BookType.objects.create(caption='男人裝')
#     return HttpResponse("ok")


def form1(request):
    if request.method == "POST":
        f = Form1(request.POST)
        if f.is_valid():
            print(f.cleaned_data)
        else:
            return render(request,"account/form1.html",{"error":f.errors,"form":f})
    else:
        # 如果不是post提交資料,就不傳引數建立物件,並將物件返回給前臺,直接生成input標籤,內容為空
        f = Form1()
        return render(request,"account/form1.html",{"form":f})
    return render(request,"account/form1.html")

Django裡面沒有手機驗證,沒有的需要自定義

示例:

#!/usr/bin/env python
# -*- coding:utf-8 -*-
import re
from django import forms
from django.core.exceptions import ValidationError


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 PublishForm(forms.Form):

    user_type_choice = (
        (0, u'普通使用者'),
        (1, u'高階使用者'),
    )

    user_type = forms.IntegerField(widget=forms.widgets.Select(choices=user_type_choice,
                                                                  attrs={'class': "form-control"}))

    title = forms.CharField(max_length=20,
                            min_length=5,
                            error_messages={'required': u'標題不能為空',
                                            'min_length': u'標題最少為5個字元',
                                            'max_length': u'標題最多為20個字元'},
                            widget=forms.TextInput(attrs={'class': "form-control",
                                                          'placeholder': u'標題5-20個字元'}))

    memo = forms.CharField(required=False,
                           max_length=256,
                           widget=forms.widgets.Textarea(attrs={'class': "form-control no-radius", 'placeholder': u'詳細描述', 'rows': 3}))

    phone = forms.CharField(validators=[mobile_validate, ],
                            error_messages={'required': u'手機不能為空'},
                            widget=forms.TextInput(attrs={'class': "form-control",
                                                          'placeholder': u'手機號碼'}))

    email = forms.EmailField(required=False,
                            error_messages={'required': u'郵箱不能為空','invalid': u'郵箱格式錯誤'},
                            widget=forms.TextInput(attrs={'class': "form-control", 'placeholder': u'郵箱'}))

Form
def publish(request):
    ret = {'status': False, 'data': '', 'error': '', 'summary': ''}
    if request.method == 'POST':
        request_form = PublishForm(request.POST)
        if request_form.is_valid():
            request_dict = request_form.clean()
            print request_dict
            ret['status'] = True
        else:
            error_msg = request_form.errors.as_json()
            ret['error'] = json.loads(error_msg)
    return HttpResponse(json.dumps(ret))

View