forms組件

来源:https://www.cnblogs.com/setcreed/archive/2019/12/03/11979697.html
-Advertisement-
Play Games

[TOC] forms組件 先拋出一個需求: 手動書寫需求 views.py 這裡實現了三個功能: 手寫html頁面獲取用戶輸入信息 將數據傳入後端做數據校驗 如果有錯誤,展示錯誤信息 但是這個頁面手寫麻煩,輸入信息寫錯了,一刷新信息全沒了,很不友好!! 使用forms組件校驗數據 使用forms組 ...


目錄

forms組件

先拋出一個需求:

1.寫一個註冊功能,獲取用戶輸入的用戶名和密碼,提交到後端,後端做校驗
2.用戶名裡面不能含有敏感信息,給出相應的提示
3.如果密碼小於三位,就提示用戶

手動書寫需求

views.py

def register(request):
    errors = {'username':'', 'password':''}
    if request.method == 'POST':
        username = request.POST.get('username')
        password = request.POST.get('password')

        if 'zf' in username:
            errors['username'] = '不能使用該字元'
        if len(password) < 4:
            errors['password'] = '密碼不能小於三位'

    return render(request, 'register.html', locals())

register.html

<form action="" method="post">
    <p>
        username:<input type="text" name="username">
        <span style="color: red">{{ errors.username }}</span>
    </p>
    <p>
        password:<input type="text" name="password">
        <span style="color: red">{{ errors.password }}</span>
    </p>
    <input type="submit">
</form>

這裡實現了三個功能:

  • 手寫html頁面獲取用戶輸入信息
  • 將數據傳入後端做數據校驗
  • 如果有錯誤,展示錯誤信息

但是這個頁面手寫麻煩,輸入信息寫錯了,一刷新信息全沒了,很不友好!!

使用forms組件校驗數據

使用forms組件首先要導入forms模塊, 寫這玩意類似於models

from django import forms

class MyForm(forms.Form):
    # username欄位 最多八位, 最少三位
    username = forms.CharField(max_length=8, min_length=3)
    # password欄位 最多八位, 最少三位
    password = forms.CharField(max_length=8, min_length=3)
    # email欄位  必須是郵箱格式
    email = forms.EmailField()

然後對數據進行校驗, 可以寫一個測試腳本,還可以使用pycharm左下角的Python Console功能,會自動搭建測試腳本

使用測試

校驗數據的方法:

  1. 給寫好的類 傳字典數據(待校驗的數據)

    form_obj = views.MyForm({'username':'cwz','password':'12','email':'123'})

  2. 如何查看校驗的數據是否合法

    form_obj.is_valid() 只有全部數據符合校驗規則才為True

  3. 如何查看不符合規則的欄位及錯誤的理由

    form_obj.errors

  4. 如何查看符合校驗規則的數據

    form_obj.cleaned_data

  5. forms組件中 定義的欄位預設都是必須傳值的 不能少傳

  6. forms組件只會校驗forms類中定義的欄位 如果你多傳了 不會有任何影響

forms組件渲染標簽

1. 方式一

forms組件只會幫你渲染用戶輸入的標簽,不會幫渲染提交按鈕標簽。

views.py

def index(request):
    # 渲染標簽,先生成一個空的form類的對象
    form_obj = MyForm()

    return render(request, 'index.html', locals())

前端頁面:

<p>forms組件渲染的方式1</p>
{{ form_obj.as_p }}
<br>
{{ form_obj.as_ul }}
<br>
{{ form_obj.as_table }}

效果:

總結:這種渲染標簽的方式封裝程度態高 不推薦使用 但是可以用在本地測試

2. 方式二

不推薦使用,比較麻煩

<p>forms組件渲染標簽方式2:</p>
{{ form_obj.username.label }}{{ form_obj.username }}
{{ form_obj.password.label }}{{ form_obj.password }}
{{ form_obj.email.label }}{{ form_obj.email }}

3.方式三

<p>forms組件渲染標簽方式3:</p>
{% for form in form_obj %}
    <p>{{ form.label }} {{ form }}</p>
{% endfor %}

若想要label標簽顯示中文,可以指定label標簽:

from django import forms

class MyForm(forms.Form):
    # username欄位 最多八位, 最少三位
    username = forms.CharField(max_length=8, min_length=3, label='用戶名')
    # password欄位 最多八位, 最少三位
    password = forms.CharField(max_length=8, min_length=3, label='密碼')
    # email欄位  必須是郵箱格式
    email = forms.EmailField(label='郵箱')

forms組件展示信息

<form action="" method="post">
    {% for form in form_obj %}
        <p>{{ form.label }} {{ form }}</p>
    {% endfor %}
    <input type="submit">
</form>

views.py

from django import forms

class MyForm(forms.Form):
    # username欄位 最多八位, 最少三位
    username = forms.CharField(max_length=8, min_length=3, label='用戶名')
    # password欄位 最多八位, 最少三位
    password = forms.CharField(max_length=8, min_length=3, label='密碼')
    # email欄位  必須是郵箱格式
    email = forms.EmailField(label='郵箱')

def index(request):
    # 渲染標簽,先生成一個空的forms類的對象
    form_obj = MyForm()

    if request.method == 'POST':
        form_obj = MyForm(request.POST)
        if form_obj.is_valid():
            print(form_obj.cleaned_data)
            return HttpResponse('數據正確')
        else:
            print(form_obj.errors)

    return render(request, 'index.html', locals())

這玩意是前端做的校驗

註意:

數據的校驗通常前後端都有,但是前端的校驗不堪一擊,可有可無;後端的校驗必須要有而且必須非常全面

在前端form表單加上一個參數(novalidate),就可以不做校驗:<form action="" method="post" novalidate>

前端錯誤信息展示寫法:

<form action="" method="post" novalidate>
    {% for form in form_obj %}
        <p>{{ form.label }} {{ form }}
            <span>{{ form.errors.0 }}</span>
        </p>

    {% endfor %}
    <input type="submit">
</form>

也支持中文顯示信息

from django import forms

class MyForm(forms.Form):
    # username欄位 最多八位, 最少三位
    username = forms.CharField(max_length=8, min_length=3, label='用戶名', error_messages={
        'max_length': '用戶名最長八位',
        'min_length': '用戶名最短三位',
        'required': '用戶名不能為空',
    })
    # password欄位 最多八位, 最少三位
    password = forms.CharField(max_length=8, min_length=3, label='密碼', error_messages={
        'max_length': '密碼最長八位',
        'min_length': '密碼最短三位',
        'required': '密碼不能為空',
    })
    # email欄位  必須是郵箱格式
    email = forms.EmailField(label='郵箱', error_messages={
        'required': '郵箱不能為空',
        'invalid': '郵箱格式不正確'
    })

form組件自定義校驗

RegexValidator驗證器

from django import forms
from django.core.validators import RegexValidator

class MyForm(forms.Form):
    # username欄位 最多八位, 最少三位
    username = forms.CharField(max_length=8, min_length=3, label='用戶名', error_messages={
        'max_length': '用戶名最長八位',
        'min_length': '用戶名最短三位',
        'required': '用戶名不能為空',
    })
    # password欄位 最多八位, 最少三位
    password = forms.CharField(max_length=8, min_length=3, label='密碼', error_messages={
        'max_length': '密碼最長八位',
        'min_length': '密碼最短三位',
        'required': '密碼不能為空',
    }, validators=[
        RegexValidator(r'^[0-9]+$', '請輸入數字'),
        RegexValidator(r'^139[0-9]+$', '數字必須要以139開頭')   # 可以添加多個正則表達式,從上往下校驗
    ]
    )

鉤子函數 (HOOK)

當你覺得上面的所有校驗還是不能滿足需求,可以考慮鉤子函數

全局鉤子

我們在Fom類中定義 clean() 方法,就能夠實現對欄位進行全局校驗。

class MyForm(forms.Form):
    # username欄位 最多八位, 最少三位
    username = forms.CharField(max_length=8, min_length=3, label='用戶名', error_messages={
        'max_length': '用戶名最長八位',
        'min_length': '用戶名最短三位',
        'required': '用戶名不能為空',
    })
    # password欄位 最多八位, 最少三位
    password = forms.CharField(max_length=8, min_length=3, label='密碼', error_messages={
        'max_length': '密碼最長八位',
        'min_length': '密碼最短三位',
        'required': '密碼不能為空',
    })

    re_password = forms.CharField(max_length=8, min_length=3, label='確認密碼', error_messages={
        'max_length': '確認密碼最長八位',
        'min_length': '確認密碼最短三位',
        'required': '確認密碼不能為空',
    })

    # 校驗密碼 確認密碼是否一致
    def clean(self):
        password = self.cleaned_data.get('password')
        re_password = self.cleaned_data.get('password')
        if not password == re_password:
            self.add_error('re_password', '兩次,密碼不一致')

        return self.cleaned_data

局部鉤子

我們在Fom類中定義 clean_欄位名() 方法,就能夠實現對特定欄位進行校驗。

class MyForm(forms.Form):
    # username欄位 最多八位, 最少三位
    username = forms.CharField(max_length=8, min_length=3, label='用戶名', error_messages={
        'max_length': '用戶名最長八位',
        'min_length': '用戶名最短三位',
        'required': '用戶名不能為空',
    })
    # password欄位 最多八位, 最少三位
    password = forms.CharField(max_length=8, min_length=3, label='密碼', error_messages={
        'max_length': '密碼最長八位',
        'min_length': '密碼最短三位',
        'required': '密碼不能為空',
    })

    re_password = forms.CharField(max_length=8, min_length=3, label='確認密碼', error_messages={
        'max_length': '確認密碼最長八位',
        'min_length': '確認密碼最短三位',
        'required': '確認密碼不能為空',
    })

    # 校驗用戶名中不能有666
    def clean_username(self):
        username = self.cleaned_data.get('username')
        if '666' in username:
            # 給username欄位添加錯誤信息
            self.add_error('username', '666是不存在的')
        # 將username返回出去
        return username

forms組件補充知識點

其他欄位參數

label input對應的提示信息

initial 預設值

required 預設為True 控制欄位是否必填

class MyForm(forms.Form):
    # username欄位 最多八位, 最少三位
    username = forms.CharField(max_length=8, min_length=3, label='用戶名', initial='預設值', 
        error_messages={
        'max_length': '用戶名最長八位',
        'min_length': '用戶名最短三位',
        'required': '用戶名不能為空',
                        }, required=False)

widget 給input框設置樣式及屬性

password = forms.CharField(max_length=8, min_length=3, label='密碼', error_messages={
        'max_length': '密碼最長八位',
        'min_length': '密碼最短三位',
        'required': '密碼不能為空',
    }, widget=forms.widgets.PasswordInput()  # 這個password欄位是密文的
username = forms.CharField(max_length=8, min_length=3, label='用戶名', initial='預設值',
                               error_messages={
                                   'max_length': '用戶名最長八位',
                                   'min_length': '用戶名最短三位',
                                   'required': '用戶名不能為空',
                               }, required=False,
                               widget=forms.widgets.TextInput({'class': 'form-control c1 c2', 'username': 'cwz'})
                               )

error_messages

重寫錯誤信息。

class LoginForm(forms.Form):
    username = forms.CharField(
        min_length=8,
        label="用戶名",
        initial="張三",
        error_messages={
            "required": "不能為空",
            "invalid": "格式錯誤",
            "min_length": "用戶名最短8位"
        }
    )
    pwd = forms.CharField(min_length=6, label="密碼")

password

class LoginForm(forms.Form):
    ...
    pwd = forms.CharField(
        min_length=6,
        label="密碼",
        widget=forms.widgets.PasswordInput(attrs={'class': 'c1'}, render_value=True)
    )

radioSelect

單radio值為字元串

class LoginForm(forms.Form):
    username = forms.CharField(
        min_length=8,
        label="用戶名",
        initial="張三",
        error_messages={
            "required": "不能為空",
            "invalid": "格式錯誤",
            "min_length": "用戶名最短8位"
        }
    )
    pwd = forms.CharField(min_length=6, label="密碼")
    gender = forms.fields.ChoiceField(
        choices=((1, "男"), (2, "女"), (3, "保密")),
        label="性別",
        initial=3,
        widget=forms.widgets.RadioSelect()
    )

單選Select

class LoginForm(forms.Form):
    ...
    hobby = forms.ChoiceField(
        choices=((1, "籃球"), (2, "足球"), (3, "雙色球"), ),
        label="愛好",
        initial=3,
        widget=forms.widgets.Select()
    )

多選Select

class LoginForm(forms.Form):
    ...
    hobby = forms.MultipleChoiceField(
        choices=((1, "籃球"), (2, "足球"), (3, "雙色球"), ),
        label="愛好",
        initial=[1, 3],
        widget=forms.widgets.SelectMultiple()
    )

單選checkbox

class LoginForm(forms.Form):
    ...
    keep = forms.ChoiceField(
        label="是否記住密碼",
        initial="checked",
        widget=forms.widgets.CheckboxInput()
    )

多選checkbox

class LoginForm(forms.Form):
    ...
    hobby = forms.MultipleChoiceField(
        choices=((1, "籃球"), (2, "足球"), (3, "雙色球"),),
        label="愛好",
        initial=[1, 3],
        widget=forms.widgets.CheckboxSelectMultiple()
    )

choice欄位註意事項

在使用選擇標簽時,需要註意choices的選項可以配置從資料庫中獲取,但是由於是靜態欄位 獲取的值無法實時更新,需要重寫構造方法從而實現choice實時更新

方式一

from django.forms import Form
from django.forms import widgets
from django.forms import fields

 
class MyForm(Form):
 
    user = fields.ChoiceField(
        # choices=((1, '上海'), (2, '北京'),),
        initial=2,
        widget=widgets.Select
    )
 
    def __init__(self, *args, **kwargs):
        super(MyForm,self).__init__(*args, **kwargs)
        # self.fields['user'].choices = ((1, '上海'), (2, '北京'),)
        # 或
        self.fields['user'].choices = models.Classes.objects.all().values_list('id','caption')

方式二

from django import forms
from django.forms import fields
from django.forms import models as form_model

 
class FInfo(forms.Form):
    authors = form_model.ModelMultipleChoiceField(queryset=models.NNewType.objects.all())  # 多選
    # authors = form_model.ModelChoiceField(queryset=models.NNewType.objects.all())  # 單選

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • Java抽象類: 抽象類特點 :抽象類除了不能實例化對象之外,類的其它功能依然存在,成員變數、成員方法和構造方法的訪問方式和普通類一樣。 由於抽象類不能實例化對象,所以抽象類必須被extends [抽象類]方式 繼承才能被使用。 抽象類表示的是一種繼承關係。 (總結就是:抽象類裡面設計跟普通類一樣, ...
  • lua中json和table的互轉,是我們在平時開發過程中經常用到的。比如: 在用lua編寫的伺服器中,如果客戶端發送json格式的數據,那麼在lua處理業務邏輯的時候,必然需要轉換成lua自己的數據結構,如table。此時,就會用到table和json格式的互轉。 在用lua編寫的伺服器中,如果我 ...
  • 先定義消息類型 orders.proto 在GOPATH創建目錄和編譯這個消息類型輸出到該目錄,包名是message 編寫go文件進行序列化和反序列化剛纔生成的包里的類型結構體數據 ...
  • swap(a,b) 用於交換a,b兩個變數的值; max(a,b) 返回a,b中的最大值; min(a,b) 返回a,b中的最小值; abs(x) 返回x的絕對值,x必須是整數; ...
  • ——日拱一卒,不期而至! 你好,我是彤哥,本篇是netty系列的第六篇。 簡介 上一章我們一起學習了Java NIO的核心組件Channel,它可以看作是實體與實體之間的連接,而且需要與Buffer交互,這一章我們就來學習一下Buffer的特性。 概念 Buffer用於與Channel交互時使用,通 ...
  • 前言 "上文" 我們介紹了JDK中的線程池框架 。我們知道,只要需要創建線程的情況下,即使是在單線程模式下,我們也要儘量使用 。即: 但是,在 "《阿裡巴巴Java開發手冊》" 中有一條 【強制】線程池不允許使用 Executors 去創建,而是通過 ThreadPoolExecutor 的方式,這 ...
  • PyCharm 是一種 Python IDE,可以幫助程式員節約時間,提高生產效率。那麼具體如何使用呢?本文從 PyCharm 安裝到插件、外部工具、專業版功能等進行了一一介紹,希望能夠幫助到大家。 機器之心之前也沒系統地介紹過 PyCharm,怎樣配置環境、怎樣 DeBug、怎樣同步 GitHub ...
  • 前言本文的文字及圖片來源於網路,僅供學習、交流使用,不具有任何商業用途,版權歸原作者所有,如有問題請及時聯繫我們以作處理。 作者:醍醐三葉 關於python的存儲問題, (1)由於python中萬物皆對象,所以python的存儲問題是對象的存儲問題,並且對於每個對象,python會分配一塊記憶體空間去 ...
一周排行
    -Advertisement-
    Play Games
  • Dapr Outbox 是1.12中的功能。 本文只介紹Dapr Outbox 執行流程,Dapr Outbox基本用法請閱讀官方文檔 。本文中appID=order-processor,topic=orders 本文前提知識:熟悉Dapr狀態管理、Dapr發佈訂閱和Outbox 模式。 Outbo ...
  • 引言 在前幾章我們深度講解了單元測試和集成測試的基礎知識,這一章我們來講解一下代碼覆蓋率,代碼覆蓋率是單元測試運行的度量值,覆蓋率通常以百分比表示,用於衡量代碼被測試覆蓋的程度,幫助開發人員評估測試用例的質量和代碼的健壯性。常見的覆蓋率包括語句覆蓋率(Line Coverage)、分支覆蓋率(Bra ...
  • 前言 本文介紹瞭如何使用S7.NET庫實現對西門子PLC DB塊數據的讀寫,記錄了使用電腦模擬,模擬PLC,自至完成測試的詳細流程,並重點介紹了在這個過程中的易錯點,供參考。 用到的軟體: 1.Windows環境下鏈路層網路訪問的行業標準工具(WinPcap_4_1_3.exe)下載鏈接:http ...
  • 從依賴倒置原則(Dependency Inversion Principle, DIP)到控制反轉(Inversion of Control, IoC)再到依賴註入(Dependency Injection, DI)的演進過程,我們可以理解為一種逐步抽象和解耦的設計思想。這種思想在C#等面向對象的編 ...
  • 關於Python中的私有屬性和私有方法 Python對於類的成員沒有嚴格的訪問控制限制,這與其他面相對對象語言有區別。關於私有屬性和私有方法,有如下要點: 1、通常我們約定,兩個下劃線開頭的屬性是私有的(private)。其他為公共的(public); 2、類內部可以訪問私有屬性(方法); 3、類外 ...
  • C++ 訪問說明符 訪問說明符是 C++ 中控制類成員(屬性和方法)可訪問性的關鍵字。它們用於封裝類數據並保護其免受意外修改或濫用。 三種訪問說明符: public:允許從類外部的任何地方訪問成員。 private:僅允許在類內部訪問成員。 protected:允許在類內部及其派生類中訪問成員。 示 ...
  • 寫這個隨筆說一下C++的static_cast和dynamic_cast用在子類與父類的指針轉換時的一些事宜。首先,【static_cast,dynamic_cast】【父類指針,子類指針】,兩兩一組,共有4種組合:用 static_cast 父類轉子類、用 static_cast 子類轉父類、使用 ...
  • /******************************************************************************************************** * * * 設計雙向鏈表的介面 * * * * Copyright (c) 2023-2 ...
  • 相信接觸過spring做開發的小伙伴們一定使用過@ComponentScan註解 @ComponentScan("com.wangm.lifecycle") public class AppConfig { } @ComponentScan指定basePackage,將包下的類按照一定規則註冊成Be ...
  • 操作系統 :CentOS 7.6_x64 opensips版本: 2.4.9 python版本:2.7.5 python作為腳本語言,使用起來很方便,查了下opensips的文檔,支持使用python腳本寫邏輯代碼。今天整理下CentOS7環境下opensips2.4.9的python模塊筆記及使用 ...