Django--組件--forms(1)-介紹&使用語法&註冊案例

一:引言

1:爲何瞭解forms組件?

顧名思義,forms組件是否是和前端form標籤有關係呢?對,能夠這麼想。html

當咱們在註冊網頁的時候是否是須要校驗數據呢?就以下圖。固然註冊不符合規則是否是得有提醒,所以須要在頁面中顯示錯誤信息提示。前端

而其實這個底層過程是很複雜的,你想若是是你寫的代碼,你是否是得先對這些字段先取值,以後是否是得按不一樣規則一一校驗。校驗完後成功到無所謂,若錯誤是否是得一個一個構建錯誤信息渲染到模板的相應位置。這個過程是很複雜的。而form組件就是實現這個複雜的過程。python

 

2:forms組件的做用?

(1)校驗數據數據庫

(2)頁面顯示錯誤信息django

(3)渲染頁面和重置數據後端

(4)解耦瀏覽器

 

 二:Forms組件的使用語法

 1:建立規則(建立一個forms類)

通常寫在views.py文件裏bash

from django import forms
#注意:這裏的字段必須和前端頁面input標籤的name屬性以及數據庫中的字段保持一致
class UserForm(forms.Form):  #建立校驗規則類。,必須繼承forms組件類
    name=forms.CharField(min_length=5)
    pwd=forms.IntegerField()
    email=forms.EmailField()

 內置字段:博文服務器

 

2:檢驗數據

咱們在python console中輸入檢驗網絡

>>>from app01.views import BookForm
>>>fm=BookForm({"name":"lilz","pwd":123,"email":"abc"})   #要檢驗的數據====只校驗規定的字段,規定的字段若是全對就是true,不檢驗其餘字段,其餘字段就是加進去也沒有影響 >>>fm.is_valid()  #查看是否合法,合法返回True(必須先查看是否合法
False

>>>fm.cleaned_data  #查看合法的字段
{'name': 'lilz', 'pwd': '123'} =======字典 >>>fm.errors         #查看不合法的字段
{'email': ['Enter a valid email address.', 'Enter a valid email address.']}

 

 

三:forms組件應用的案例--註冊

1:目標-實現校驗與頁面顯示信息的功能

  用戶名長度不能低於5位

  密碼必須是純數字

  郵箱必須符合郵箱格式

  若是輸入格式有錯誤,請顯示在頁面上

2:準備

(1)數據庫相關

models.py

from django.db import models

class UserInfo(models.Model):
    user=models.CharField(max_length=32)
    pwd=models.CharField(max_length=32)
    email=models.CharField(max_length=32)

 

====>數據庫遷移

python manage.py makemigrations    #同步
python manage.py migrate

3:上代碼

(1)前端頁面

template/reg.html

<style>
    .error{
        color: red;
        margin-left: 10px;
    }
</style>
<body>
    <form action="" method="post">
        {% csrf_token %}
        <p>用戶名:<input type="text"name="user"><span class="error">{{ error.name.0 }}</span></p>
        <p>密碼:<input type="password"name="pwd"><span class="error">{{ error.pwd.0 }}</span></p>
        <p>郵箱:<input type="email"name="email"><span class="error">{{ error.email.0 }}</span></p>
        <input type="submit">
    </form>
</body>

 

(2)後端代碼

urls.py

from django.contrib import admin
from django.urls import path
from app01 import views

urlpatterns = [
    path('admin/', admin.site.urls),
    path('reg/', views.reg,name='reg'),
]

 

views.py

定義forms規則

from django import forms
from app01.models import UserInfo
#注意:這裏的字段必須和前端頁面input標籤的name屬性以及數據庫中的字段保持一致
class UserForm(forms.Form):  #建立校驗規則類。,必須繼承forms組件類
    name=forms.CharField(min_length=5,error_messages={"required":"該字段不能爲空"})#error_messages表示提示錯誤消息  #required表明爲空的錯誤
    pwd=forms.IntegerField()
    email=forms.EmailField(error_messages={"invalid":"郵箱格式錯誤"})  #invalid表明格式的錯誤
def reg(request):
    if request.method=='POST':
        # 數據校驗,咱們把數據校驗代碼不放在這裏,解耦 ===UserForm校驗規則類
        form=UserForm(request.POST)    #把數據放在規則類裏校驗
        if form.is_valid():#校驗數據
            UserInfo.objects.create(**form.cleaned_data) #符合規則後咱們把數據插入到數據庫中,由於數據是字典,因此須要打散
        else:
            # print(form.cleaned_data) #{'pwd': 123, 'email': '250197@qq.com'}
            # print(type(form.cleaned_data))  # <class 'dict'>
            # print(form.errors) #<ul class="errorlist"><li>name<ul class="errorlist"><li>This field is required.</li></ul></li></ul>
            # print(type(form.errors))  #<class 'django.forms.utils.ErrorDict'>   #{"name":["",]}
            # print(type(form.errors.get("name")))  #<class 'django.forms.utils.ErrorList'>   #["",]
            # print(form.errors.get("name")[0])  #name對應的錯誤信息
            error=form.errors
            return render(request,'reg.html',locals())  #把錯誤數據渲染到模板
    else:
        return render(request,'reg.html')

 

4:效果

5:分析整個流程

(1)訪問http://127.0.0.1:8000/reg/  並輸入數據,這是一個get請求,

(2)數據經瀏覽器以http協議數據封裝經網絡到達服務器

(3)服務器在wsgi.py中以http協議解封裝,經中間件的組件到達urls.py文件找到路徑對應的視圖函數,執行reg函數,reg函數中檢查是get請求返回瀏覽器註冊頁面

(4)用戶在註冊頁面輸入數據點擊提交,這是一個標籤按鈕,而後通過form標籤中的路徑訪問服務器重複(2)(3)步驟到達reg函數,不過是post請求。

(5)post請求處理代碼中調用form規則定義類匹配數據是否合規,若合規則把數據寫入到數據庫表中,不合則把錯誤不合規則的數據渲染到前端註冊頁面,而後把註冊頁面返回給瀏覽器

四:forms組件應用的案例--註冊--優化

1:目標-實現校驗、頁面顯示信息的、渲染頁面和重置數據功能

本案例在上面案例的基礎上實現

首先分析下上面的案例的缺陷,缺陷一:前端頁面input還須要咱們本身寫,這比較麻煩;缺陷二:前端頁面輸入格式錯誤,雖然有提示錯誤,但咱們輸入的數據也已經沒有了。咱們的目標就是使用forms組件解決這缺陷。

2:須要知識點--實現渲染

方法一:簡單但不靈活

前端頁面reg.html

 

對於<label>/<input> 對,還有幾個輸出選項:

  • {{ form.as_table }} 以表格的形式將它們渲染在<tr> 標籤中
  • {{ form.as_p }} 將它們渲染在<p> 標籤中
  • {{ form.as_ul }} 將它們渲染在<li> 標籤中
<body>
    <form action="">
        {% csrf_token %}
        {{ form.as_p }} </form>
</body>

 

後端view

def reg(request):
    if request.method=='POST':
          pass
    else:
        form=UserForm()  #沒有把咱們輸入的數據放進去查看是否匹配規則。咱們的目的是把UserForm規則類的字段渲染到頁面
        return render(request,'reg.html',locals())    

 

效果:

缺陷:

這種方法把樣式寫死了,雖然這種方法簡單

 


 

方法二:(能實現保留數據,關鍵點在forms對象渲染)靈活但複雜

 前端頁面:

<style>
    .error{
        color: red;
        margin-left: 10px;
    }
</style>
<body>
    <form action="" method="post">
        {% csrf_token %}
        <p>用戶名:{{ form.name }}<span class="error">{{ error.name.0 }}</span></p>
        <p>密碼:{{ form.pwd }}<span class="error">{{ error.pwd.0 }}</span></p>
        <p>郵箱:{{ form.email }}<span class="error">{{ error.email.0 }}</span></p>
        <input type="submit">
    </form>
</body>

後端view

def reg(request):
    if request.method=='POST':
        # 數據校驗,咱們把數據校驗代碼不放在這裏,解耦 ===UserForm校驗規則類
        form=UserForm(request.POST)    #把數據放在規則類裏校驗
        if form.is_valid():#校驗數據
            UserInfo.objects.create(**form.cleaned_data) #符合規則後咱們把數據插入到數據庫中,由於數據是字典,因此須要打散
        else:
            error=form.errors
            return render(request,'reg.html',locals())  #把錯誤數據渲染到模板
    else:
        form=UserForm()  #沒有把咱們輸入的數據放進去查看是否匹配規則。咱們的目的是把UserForm規則類的字段渲染到頁面
        return render(request,'reg.html',locals())

 


 

 

現象

針對效果咱們作下面分析

現象分析一:前端出現驗證效果

正是由於咱們定義的規則屬性加入到了標籤內,前端纔可以在頁面就能夠控制匹配規則。這是瀏覽器的機制。每一個瀏覽器都有不一樣的機制。這樣是不靠譜的仍是得用後端的匹配規則機制才行,固然前端有也是不錯的。

 那麼該如何才能讓前端不參與任何校驗呢?

下面加入novalidate就可以達到此目的

    <form action="" method="post" novalidate>
        {% csrf_token %}
        <p>用戶名:{{ form.name }}<span class="error">{{ error.name.0 }}</span></p>
        <p>密碼:{{ form.pwd }}<span class="error">{{ error.pwd.0 }}</span></p>
        <p>郵箱:{{ form.email }}<span class="error">{{ error.email.0 }}</span></p>
        <input type="submit">
    </form>

 

 現象分析二:前端的寫過的數據依然保留--重置數據

 

爲何會這樣呢?咱們來分析下

(1)首先咱們訪問http://127.0.0.1:8000/reg/  get請求

(2)到達視圖函數因爲get請求,form=UserForm()是不帶數據的,那麼就會返回給瀏覽器渲染後的reg.html文件。

(3)當咱們輸入數據,點擊提交按鈕時,此時根據

<form action="" method="post">
依然會訪問http://127.0.0.1:8000/reg/  

 不過此時是post請求。而這個時候form=UserForm(request.POST)是帶着數據的

(4)由於        <p>用戶名:{{ form.name }}<span class="error">{{ error.name.0 }}</span></p>  

 {{ form.name }}這個位置沒有寫死,   就會渲染出原來request.POST中的數據給瀏覽器

 

 


缺陷:

<p>用戶名:{{ form.name }}<span class="error">{{ error.name.0 }}</span></p>    中的  {{ form.name }}  是渲染出來的,那麼咱們就沒法對它更改樣式了。也就是咱們對這個input標籤沒法更改屬性。

 

下面的方法就會解決這個問題====在定義的forms規則類中加屬性

from django.forms import widgets   #widgets魔法工具包

class UserForm(forms.Form):  #建立校驗規則類。,必須繼承forms組件類
    name=forms.CharField(min_length=5,
                         error_messages={"required":"該字段不能爲空"},
                         widget=widgets.TextInput(attrs={"class":"from-control"})
                         )   #TextInput表示input標籤type=text
########################################################
#關於widget:

 # 每一個表單字段都有一個對應的Widget 類,它對應一個HTML 表單Widget,例如<input type="text">

 # 在大部分狀況下,字段都具備一個合理的默認Widget。例如,默認狀況下,CharField 具備一個TextInput Widget,它在HTML 中生成一個<input type="text">

 

 或者還有一種給屬性添加類的方法:

from django import forms
from django.forms import widgets 
class UserForm(forms.Form):
    user=forms.CharField(min_length=5,label="用戶名")
    pwd=forms.CharField(min_length=5,widget=widgets.PasswordInput(),label="密碼") #密碼須要密文
    r_pwd=forms.CharField(min_length=5,widget=widgets.PasswordInput(),label="確認密碼")
    email=forms.EmailField(min_length=5,label="郵箱")

    # class Meta:  #控制UserForm類的元類信息
    def __init__(self, *args, **kwargs):#至關於修改forms類的__init__方法
        super().__init__(*args, **kwargs)  #走父類的這個方法
        for filed in self.fields.values():  #循環每一個字段對象
            filed.widget.attrs.update({'class': 'form-control'})  #對每一個屬性添加一個類

 

 

 

方法三:

後端:

規則類

class UserForm(forms.Form):  #建立校驗規則類。,必須繼承forms組件類
    name=forms.CharField(min_length=5,label="用戶名")   
    pwd=forms.IntegerField(label="密碼")
    email=forms.EmailField(label="郵箱")

 

views---沒有變更

def reg(request):
    if request.method=='POST':
        # 數據校驗,咱們把數據校驗代碼不放在這裏,解耦 ===UserForm校驗規則類
        form=UserForm(request.POST)    #把數據放在規則類裏校驗
        if form.is_valid():#校驗數據
            UserInfo.objects.create(**form.cleaned_data) #符合規則後咱們把數據插入到數據庫中,由於數據是字典,因此須要打散
        else:

            error=form.errors
            return render(request,'reg.html',locals())  #把錯誤數據渲染到模板
    else:
        form=UserForm()  #沒有把咱們輸入的數據放進去查看是否匹配規則。咱們的目的是把UserForm規則類的字段渲染到頁面
        return render(request,'reg.html',locals())
View Code

 

前端頁面

<style>
    .error{
        color: red;
        margin-left: 10px;
    }
</style>
<body>
    <form action="" method="post" novalidate>
        {% csrf_token %}
        {% for field in form %} <div>
            <label for="">{{ field.label }}</label> {# 顯示字段名:#} {{ field }}{# 顯示input框:#} <span class="error">{{ field.errors }}</span> {# 顯示錯誤信息:#} </div> {% endfor %} <input type="submit">
    </form>
</body>

 

效果:

 


 

參考:

配齊博文

Yuan先生

相關文章
相關標籤/搜索