1. 程式人生 > 實用技巧 >小談Django中的form元件

小談Django中的form元件

form

簡單Form示例

定義

from django import forms


class RegForm(forms.Form):
    user = forms.CharField(label="賬號")
    pwd = forms.CharField(label="密碼", widget=forms.PasswordInput)

使用

檢視函式

def reg(request):
    form_obj = RegForm()
    if request.method == 'POST':
        form_obj = RegForm(request.POST)
        if form_obj.is_valid():
            print(request.POST)
            # 上面的顯示結果: 
            # <QueryDict: {'csrfmiddlewaretoken': ['wFp3cnKRpV1ZMuOdZl0rklwWkncSfULWeWaDPhaBa9eObp0Vnl4JBgZqj7MJuy4t'], 'user': ['alex'], 'pwd': ['123']}>
            print(form_obj.cleaned_data, type(form_obj.cleaned_data))
            # 上面的顯示結果: 
            # {'user': 'alex', 'pwd': '123'} <class 'dict'>
            return HttpResponse('註冊成功')

    return render(request, 'reg.html', {'form_obj': form_obj})

模板

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="" method="post" novalidate>
    {% csrf_token %}
{#    {{ form_obj.as_p }}#}

    <p>
        <label for="{{ form_obj.user.id_for_label }}">{{ form_obj.user.label }}</label>
        {{ form_obj.user }} <span>{{ form_obj.user.errors.0 }}</span>
    </p>
    <p>
        <label for="{{ form_obj.pwd.id_for_label }}">{{ form_obj.pwd.label }}</label>
        {{ form_obj.pwd }}
    </p>
    {{ form_obj.errors }}
    <button>註冊</button>
</form>
</body>
</html>

模板更多

  • forms.Charfield --> 欄位物件
  • widget --> 外掛物件

生成所有欄位的input框

{{ form_obj.as_p }}

生成某個欄位的input框

{{ form_obj.user }}

某個欄位的中文提示

{{ form_obj.user.label }}

某個欄位的input框的ID

{{ form_obj.user.id_for_label }}

生成單個的input框並且設定label標籤

<p>
    <label for="{{ form_obj.user.id_for_label }}">{{ form_obj.user.label }}</label>
    {{ form_obj.user }}
</p>
<label for="{{ form_obj.user.id_for_label }}"> -> 作用: 讓input框聚焦 -> 滑鼠點選"賬號"游標自動切到input框中

所有欄位的校驗錯誤

{{ form_obj.errors }} -> 所有欄位的所有錯誤
{{ form_obj.errors.0 }} -> 所有欄位的第一個錯誤

某個欄位的校驗錯誤

{{ form_obj.user.errors }} -> 某個欄位的所有錯誤
{{ form_obj.user.errors.0 }} -> 某個欄位的第一個錯誤

widget=forms.PasswordInput

# input框顯示密文
class RegForm(forms.Form)L
	...
    pwd = forms.CharField(label='密碼', widget=forms.PasswordInput)

Form常用欄位和外掛

  • 欄位用於對使用者請求資料的驗證 __> 與form表單校驗相關
  • 外掛用於自動生成HTML __> 和前段渲染相關

所有欄位

# 匯入forms模組語句:
# from django import forms
# 直接點進forms有下面這句, 然後點進去fields看
from django.forms.fields import *

# 看到所有的欄位:
__all__ = (
    'Field', 'CharField', 'IntegerField',
    'DateField', 'TimeField', 'DateTimeField', 'DurationField',
    'RegexField', 'EmailField', 'FileField', 'ImageField', 'URLField',
    'BooleanField', 'NullBooleanField', 'ChoiceField', 'MultipleChoiceField',
    'ComboField', 'MultiValueField', 'FloatField', 'DecimalField',
    'SplitDateTimeField', 'GenericIPAddressField', 'FilePathField',
    'SlugField', 'TypedChoiceField', 'TypedMultipleChoiceField', 'UUIDField',
)

常用欄位只寫了三個 ; 如果樣式不夠 , 可以修改widget就可以了 , 可以點出很多東西

  • 比如ChoiceField(widget=forms.RadioSelect)
  • 比如MultipleChoiceField(widget=forms.CheckboxSelectMultiple)

Charfield

user = forms.CharField(label="賬號")

ChoiceField

gender = forms.ChoiceField(choices=(('1','男'),('2','女')),label='性別')

MultipleChoiceField

hobby = forms.MultipleChoiceField(choices=(('1','抽菸'),('2','喝酒'),('3','吐口水')), label='愛好')

inital

class RegForm(forms.Form):
    gender = forms.ChoiceField(choices=(('1','男'),('2','女')),label='性別', initial='2') # 設定預設值, 渲染在前段頁面就是input框中value的值

error_messages

class RegForm(forms.Form):
    user = forms.CharField(
        label="賬號",
        min_length=6,
        # 在前段顯示錯誤的資訊; 如果不設定, 顯示的是預設的,英文的
        error_messages={
            'required': '不能為空!',
            'min_length':'至少是6位!'
        }
    )

widget

# 前段的input框顯示密文
class RegForm(forms.Form)L
	...
    pwd = forms.CharField(label='密碼', widget=forms.PasswordInput)
# widget=forms.PasswordInput
# 上下兩個一樣,主要看點進去"from django import forms"中的forms,看模組如何匯入的.
# widget=forms.widgets.PasswordInput

required

class RegForm(forms.Form):
    user = forms.CharField(
        # required預設是True_>必填的;改成False可以不填
        required=False,
        label="賬號",
        min_length=6,
        # 在前段顯示錯誤的資訊; 如果不設定, 顯示的是預設的,英文的
        error_messages={
            'required': '不能為空!',
            'min_length':'至少是6位!'
        }
    )

disabled

是否禁用

min_length

最小長度

choices

可選擇的資料

方法一 :

class RegForm(forms.Form):
    ...
    gender = forms.ChoiceField(choices=(('1','男'),('2','女')),label='性別', initial='2')
    hobby = forms.MultipleChoiceField(choices=(('1','抽菸'),('2','喝酒'),('3','吐口水')), label='愛好')

方法二 :

class RegForm(forms.Form):
    ...
    gender = forms.ChoiceField(label='性別', initial='2')    
    
    def __init__(self, *args, **kwargs):
        super(RegForm, self).__init__(*args, **kwargs)
        # self.fields['gender'].choices = [('1','男'),('2','女')]
        # 上下兩句效果一樣, 但是models中gender類得新增雙下str方法
        self.fields['gender'].choices = models.gender.objects.all()

校驗

1. 自帶的校驗規則

各個欄位都有自己自帶的校驗規則 , 比如required...

2. 自定義校驗規則

1. 寫函式

from django import forms
from django.core.exceptions import ValidationError

# value就是input框中填寫的值
def check_name(value):
    # 自定義校驗規則
    # 如果校驗合格, 什麼都不做;
    # 如果校驗不合格, 丟擲異常(ValidationError)
    if 'alex' in value:
        raise ValidationError('不能包含alex,非法字元!')

class RegForm(forms.Form):
    user = forms.CharField(
        label="賬號",
        min_length=6,
        # 自定義校驗規則
        validators=[check_name]
        error_messages={
            'required': '不能為空!',
            'min_length':'至少是6位!'
        }
    )

2. 內建校驗器

from django import forms
# RegexValidator是正則的內建校驗器,還有很多其他的, 比如: 郵箱的,url的,ipv6的,...;可以點進去看
from django.core.validators import RegexValidator

class RegForm(forms.Form):
    phone = forms.Charfield(
        # RegexValidator()例項化一個RegexValidator的物件,第一個引數是正則表示式; 第二個引數是錯誤資訊;
        # 可以點進去看看, 還有其他的,一般這兩個就夠了
        validators=[RegexValidator(r'^1[3-9]\d{9}$', '手機號格式不正確')]
    )

3. 區域性鉤子

class RegForm(forms.Form):
    user = forms.CharField(
        label="賬號",
        min_length=6,
        error_messages={
            'required': '不能為空!',
            'min_length':'至少是6位!'
        }
    )
    
    def clean_user(self):
        # 區域性鉤子 clean_欄位名
        # 如果校驗成功, 返回當前欄位的值;
        # 如果校驗不成功, 丟擲異常;
        if 'alex' in self.cleaned_data.get('user'):
            raise ValidationError('不能包含alex,非法字元!')
        return self.cleaned_data.get('user')

4. 全域性鉤子

class RegForm(forms.Form):
    pwd = forms.CharField(label="密碼", widget=forms.PasswordInput)
    re_pwd = forms.CharField(label="密碼", widget=forms.PasswordInput)
    ...
    
    def clean(self):
        # 全域性鉤子
        # 如果校驗成功, 返回所有欄位的值;
        # 如果校驗不成功, 丟擲異常;
        pwd = self.cleaned_data.get('pwd')
        re_pwd = self.cleaned_data.get('re_pwd')
        if pwd == re_pwd:
            return self.cleaned_data
        else:
            # 這樣錯誤資訊就在re_pwd後面顯示了,不寫的話只會在所有欄位的所有錯誤中出現;
            self.add_error('re_pwd','兩次密碼不一致!!!')
            raise ValidationError('兩次密碼不一致!')
  • 如果要定義的校驗規則只針對於一個欄位使用 __> 區域性鉤子 ;
  • 如果要定義的校驗規則針對 一個Form中的兩個欄位合起來做校驗( 如密碼和確認密碼 ) __> 全域性鉤子 ;
  • 如果要定義的校驗規則適用於多個欄位 __> 寫函式或者內建校驗器 , 可以只寫一次函式 , 然後把函式名寫到每個欄位的validators中 ;