1. 程式人生 > >Django 中的Form表單認證

Django 中的Form表單認證

ons ios ive har emp 幫助 field類 含義 ack

一、Form表單

?

1.1 Form的幾個功能
  1. 驗證用戶數據(顯示錯誤信息)

  2. 初始化頁面顯示內容

  3. HTML Form提交保留上次提交數據

  4. 生成HTML標簽

?

1.2 創建表單類Form

1. 創建的類必須繼承類:forms.Form

2. 字段名必須與前端表單中的名稱一致(完全一樣)

3. Field類是所有其他類的基類

#!/usr/bin/env python
# -*- coding:utf-8 -*-
import re

from django import forms
from django.forms import fields
from django.forms import widgets
from django.forms import ValidationError

def mobile_validate(value):
    pattern_mobile= '^(13[0-9]|15[012356789]|17[678]|18[0-9]|14[57])[0-9]{8}$'
    if not re.match(pattern_mobile, str(value)):

        raise ValidationError('手機號碼格式錯誤')

class UserForm(forms.Form):

    user = fields.CharField(
        min_length=4,
        max_length=12,
        error_messages={
            "required": "用戶名不能為空",
            "min_length": "長度必須大於4",
            "max_length": "長度必須小於12"
        }
    )
    email = fields.EmailField(
        error_messages={
            "required": "郵箱不能為空",
            "invalid": "格式不合法"
        }
    )
    wechat = fields.CharField(
        error_messages={
            "required": "微信號還是填上吧!"
        }
    )
    phone_number = fields.IntegerField(
        # validators= ['^1[3-8]{2}\d{8}$',],
        validators= [mobile_validate,],
        error_messages= {
            "required": "手機號不能為空",
            "invalid": "手機號格式有誤"
        }
    )
    group = fields.ChoiceField(
        choices=((1,"普通用戶"), (2, "員工用戶"), (3, "黑名單")),
        error_messages={
            "required": "用戶類型必選",
            "invalid": "只能為選擇框中的內容"
        }
    )
    partment = fields.ChoiceField(
        choices=(
            (0,"人力資源"),
            (1,"運營維護"),
            (2,"銷售部"),
            (3,"開發部"),
            (4,"項目部"),
            (5,"後勤管理"),
        ),
        error_messages = {
            "required": "所屬部門必選",
            "invalid": "必須為提供的選項中的值"
        }
    )

?
1.3 視圖函數處理

  1. HTML Form提交保留上次提交數據 及“GET”方式提交生成form內的標簽
    實現方式:在"GET"方法內生成一個Form對象 obj = my_form.UserForm() 並傳入前端

  2. 驗證用戶數據
    實現方式:在"POST"方法中創建一個Form對象並把POT提交的數據傳入
    obj = my_form.UserForm(request.POST)
    if obj.is_valid():
    ????data = obj.cleaned_data
    ????#在這兒去數據庫創建數據
    ????# models.User.objects.create(**data)

    else:
    ????errors = obj.errors.as_data()

def adduser(request):
    """使用Form表單驗證,新增用戶是否合法"""
    users = models.User.objects.all()
    if request.method == "GET":
        obj = my_form.UserForm()  #這兒就能保證上次的錯誤信息還給保留
        response = render(request, 'cmdb/usermanage.html',{
            "obj": obj,  
            "users": users,
        })
    elif request.method == "POST":
        obj = my_form.UserForm(request.POST)
        if obj.is_valid():
            data = obj.cleaned_data
            #在這兒去數據庫創建數據
            # models.User.objects.create(**data)
        else:
            errors = obj.errors.as_data()
        response = render(request, 'cmdb/usermanage.html', {
            "users": users,
            "obj":obj,
        })
    return response

?
1.4 Form驗證時幾個方法代表的含義

  • obj = UserForm(request.POST) #生成一個將要驗證的對象

1. obj.is_valid() #開始驗證, 所有數據驗證過了返回True 有一個錯誤就返回False

2. obj.cleaned_data #所有正確的數據都在這裏面
obj.clearned_data.as_json() #json 格式展示數據
obj.cleaned_data.as_data

3. obj.errors #包含了所有驗證錯誤的方法

?
1.5 前端生成html標簽

  • obj = my_form.UserForm() #已將標簽打包

  • response = render(request, ‘url‘,{"obj": obj, "users": users,}) #將數據傳入前端

  1. obj.user 會自動生成 <input type="text" name="user"/>標簽,同理其他
    在此我使用的表格形式
<form action="/cmdb/add-user/" method="POST">
{% csrf_token %}
<tr option="add">
    <td>{{ obj.user }}<span class="error_msg">{{ obj.errors.user.0 }}</span></td>
    <td>{{ obj.email }}<span class="error_msg">{{ obj.errors.email.0 }}</span></td>
    <td>{{ obj.wechat }}<span class="error_msg">{{ obj.errors.wechat.0 }}</span></td>
    <td>{{ obj.phone_number }}<span class="error_msg">{{ obj.errors.phone_number.0 }}</span></td>
    <td>{{ obj.group }}<span class="error_msg">{{ obj.errors.group.0 }}</span></td>
    <td>{{ obj.partment }}<span class="error_msg">{{ obj.errors.partment.0 }}</span></td>
    <td>默認當前時間</td>
    <td style="width: 80px">
        <input type="submit" value="新增用戶"/>
    </td
</tr>

實際效果

技術分享圖片

?
二、Form中的參數

創建Form類時,主要涉及到 【字段】 和 【插件】,字段用於對用戶請求數據的驗證,插件用於自動生成HTML;

  1. 內置字段如下:
Field
    required=True,               是否允許為空
    widget=None,                 HTML插件
    label=None,                  用於生成Label標簽或顯示內容
    initial=None,                初始值
    help_text='',                幫助信息(在標簽旁邊顯示)
    error_messages=None,         錯誤信息 {'required': '不能為空', 'invalid': '格式錯誤'}
    show_hidden_initial=False,   是否在當前插件後面再加一個隱藏的且具有默認值的插件(可用於檢驗兩次輸入是否一直)
    validators=[],               自定義驗證規則
    localize=False,              是否支持本地化
    disabled=False,              是否可以編輯
    label_suffix=None            Label內容後綴
 
 
CharField(Field)
    max_length=None,             最大長度
    min_length=None,             最小長度
    strip=True                   是否移除用戶輸入空白
 
IntegerField(Field)
    max_value=None,              最大值
    min_value=None,              最小值
 
FloatField(IntegerField)
    ...
 
DecimalField(IntegerField)
    max_value=None,              最大值
    min_value=None,              最小值
    max_digits=None,             總長度
    decimal_places=None,         小數位長度
 
BaseTemporalField(Field)
    input_formats=None          時間格式化   
 
DateField(BaseTemporalField)    格式:2015-09-01
TimeField(BaseTemporalField)    格式:11:12
DateTimeField(BaseTemporalField)格式:2015-09-01 11:12
 
DurationField(Field)            時間間隔:%d %H:%M:%S.%f
    ...
 
RegexField(CharField)
    regex,                      自定制正則表達式
    max_length=None,            最大長度
    min_length=None,            最小長度
    error_message=None,         忽略,錯誤信息使用 error_messages={'invalid': '...'}
 
EmailField(CharField)      
    ...
 
FileField(Field)
    allow_empty_file=False     是否允許空文件
 
ImageField(FileField)      
    ...
    註:需要PIL模塊,pip3 install Pillow
    以上兩個字典使用時,需要註意兩點:
        - form表單中 enctype="multipart/form-data"
        - view函數中 obj = MyForm(request.POST, request.FILES)
 
URLField(Field)
    ...
 
 
BooleanField(Field)  
    ...
 
NullBooleanField(BooleanField)
    ...
 
ChoiceField(Field)
    ...
    choices=(),                選項,如:choices = ((0,'上海'),(1,'北京'),)
    required=True,             是否必填
    widget=None,               插件,默認select插件
    label=None,                Label內容
    initial=None,              初始值
    help_text='',              幫助提示
 
 
ModelChoiceField(ChoiceField)
    ...                        django.forms.models.ModelChoiceField
    queryset,                  # 查詢數據庫中的數據
    empty_label="---------",   # 默認空顯示內容
    to_field_name=None,        # HTML中value的值對應的字段
    limit_choices_to=None      # ModelForm中對queryset二次篩選
     
ModelMultipleChoiceField(ModelChoiceField)
    ...                        django.forms.models.ModelMultipleChoiceField
 
 
     
TypedChoiceField(ChoiceField)
    coerce = lambda val: val   對選中的值進行一次轉換
    empty_value= ''            空值的默認值
 
MultipleChoiceField(ChoiceField)
    ...
 
TypedMultipleChoiceField(MultipleChoiceField)
    coerce = lambda val: val   對選中的每一個值進行一次轉換
    empty_value= ''            空值的默認值
 
ComboField(Field)
    fields=()                  使用多個驗證,如下:即驗證最大長度20,又驗證郵箱格式
                               fields.ComboField(fields=[fields.CharField(max_length=20), fields.EmailField(),])
 
MultiValueField(Field)
    PS: 抽象類,子類中可以實現聚合多個字典去匹配一個值,要配合MultiWidget使用
 
SplitDateTimeField(MultiValueField)
    input_date_formats=None,   格式列表:['%Y--%m--%d', '%m%d/%Y', '%m/%d/%y']
    input_time_formats=None    格式列表:['%H:%M:%S', '%H:%M:%S.%f', '%H:%M']
 
FilePathField(ChoiceField)     文件選項,目錄下文件顯示在頁面中
    path,                      文件夾路徑
    match=None,                正則匹配
    recursive=False,           遞歸下面的文件夾
    allow_files=True,          允許文件
    allow_folders=False,       允許文件夾
    required=True,
    widget=None,
    label=None,
    initial=None,
    help_text=''
 
GenericIPAddressField
    protocol='both',           both,ipv4,ipv6支持的IP格式
    unpack_ipv4=False          解析ipv4地址,如果是::ffff:192.0.2.1時候,可解析為192.0.2.1, PS:protocol必須為both才能啟用
 
SlugField(CharField)           數字,字母,下劃線,減號(連字符)
    ...
 
UUIDField(CharField)           uuid類型
2.2 插件方法
  • from django.forms import widgets #使用插件將CharField 中的內容生成文本域 textarea 標簽
    textarea = fields.CharField(
    ????error_messages={"required": "文本域不能為空"}
    ????widget = widgets.Textarea
    )
TextInput(Input)
NumberInput(TextInput)
EmailInput(TextInput)
URLInput(TextInput)
PasswordInput(TextInput)
HiddenInput(TextInput)
Textarea(Widget)
DateInput(DateTimeBaseInput)
DateTimeInput(DateTimeBaseInput)
TimeInput(DateTimeBaseInput)
CheckboxInput
Select
NullBooleanSelect
SelectMultiple
RadioSelect
CheckboxSelectMultiple
FileInput
ClearableFileInput
MultipleHiddenInput
SplitDateTimeWidget
SplitHiddenDateTimeWidget
SelectDateWidget
常用插件
單radio,值為字符串
user = fields.CharField(
    initial=2,
    widget=widgets.RadioSelect(choices=((1,'上海'),(2,'北京'),))
)

單radio,值為字符串
user = fields.ChoiceField(
    choices=((1, '上海'), (2, '北京'),),
    initial=2,
    widget=widgets.RadioSelect
)

單select,值為字符串
user = fields.CharField(
    initial=2,
    widget=widgets.Select(choices=((1,'上海'),(2,'北京'),))
)

單select,值為字符串
user = fields.ChoiceField(
    choices=((1, '上海'), (2, '北京'),),
    initial=2,
    widget=widgets.Select
)

多選select,值為列表
user = fields.MultipleChoiceField(
    choices=((1,'上海'),(2,'北京'),),
    initial=[1,],
    widget=widgets.SelectMultiple
)

單checkbox
user = fields.CharField(
    widget=widgets.CheckboxInput()
)


多選checkbox,值為列表
user = fields.MultipleChoiceField(
    initial=[2, ],
    choices=((1, '上海'), (2, '北京'),),
    widget=widgets.CheckboxSelectMultiple

?
三、定義自己的驗證規則

1. 第一種方式自定義函數
將自定義的函數加入 validators = [] 參數中

from django.forms import ValidationError

def mobile_validate(value):
    pattern_mobile= '^(13[0-9]|15[012356789]|17[678]|18[0-9]|14[57])[0-9]{8}$'
    if not re.match(pattern_mobile, str(value)):

        raise ValidationError('手機號碼格式錯誤')

#Form類中
class UserForm(forms.Form):

    phone_number = fields.IntegerField(
        validators= [mobile_validate,],     #將自定義的函數加入validators參數中
        error_messages= {
            "required": "手機號不能為空",
            "invalid": "手機號格式有誤"
        }
    )

#或
phone_number = forms.CharField(validators=[mobile_validate, ],

                          error_messages={'required': '手機不能為空'},

                            widget=forms.TextInput(attrs={'class': "phone",

                                                          'placeholder': '+86 13356475897'}))

2. 第二種方式自定義函數
將自定義的函數加入 validators = [] 參數中

from django.core.validators import RegexValidator
 
class UserForm(Form):

    phone_number = fields.IntegerField(
        validators=[RegexValidator('^1\d{10}$', '手機號非法'), RegexValidator('^133[0-9]{8}$', '只能為聯通號')],
    )

Django 中的Form表單認證