Django Form表單


 

 閱讀目錄

 

 

 

構建一個表單

 

導入模塊

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

  

創建form類

 

from django import forms
from django.forms import widgets
from django.core.exceptions import ValidationError
import re
from django.contrib.auth.models import User


class LoginForm(forms.Form):
    # 字段名字(username)就是渲染后input標簽的name屬性
    username = forms.CharField(min_length=2, max_length=8,
                               strip=True,  # 是否移除用戶輸入空白
                               # error_messages 為錯誤觸發的錯誤信息
                               error_messages={"required": "該字段不能為空",
                               "min_length": "用戶名長度不能小於2",
                               "max_length": "用戶名長度不能大於8"},
                               # 給input添加屬性
                               widget=widgets.TextInput(attrs={
                                   "class": "form-control",
                                   "placeholder": "2-8 位中文/字母/下划線",
                                   "id": "inputname"}))

    password = forms.CharField(min_length=6,max_length=20,
                               strip=True,
                               error_messages={"required":"該字段不能為空",
                              "min_length":"密碼長度不能小於6位",
                              "max_length":"密碼長度不能大於20位"},
                              widget = widgets.PasswordInput(attrs={
                                   "class":"form-control",
                                   "placeholder":"密碼需6-20個字符",
                                   "id":"inputPassword3"}))

    check_pwd = forms.CharField(min_length=6,max_length=20,
                                strip=True,
                               error_messages={"required":"該字段不能為空",
                              "min_length":"密碼長度不能小於6位",
                              "max_length":"密碼長度不能大於20位"},
                               widget = widgets.PasswordInput(attrs={
                                   "class":"form-control",
                                   "placeholder":"請再次輸入密碼",
                                   "id":"inputPassword4"}))

    email = forms.EmailField(error_messages={'required': "郵箱不能為空", "invalid":"請輸入有效的郵箱地址"},
                             widget = widgets.EmailInput(attrs={
                                 "class":"form-control",
                                 "placeholder":"請輸入郵箱",
                                 "id":"inputemail"}))

 

 

視圖

 

from .forms import LoginForm

def form_reg(request):
    if request.method == "POST":
        login_form = LoginForm(request.POST)  # 將數據傳給對應字段  綁定數據的表單實例

        if login_form.is_valid():  # 判讀是否全部通過驗證
            print("通過驗證")
            print(login_form.cleaned_data)  # 保存全部通過驗證的表單數據 {'username': '周軍豪123', 'password': '961023hao'}
            username = login_form.cleaned_data.get("username")
            password = login_form.cleaned_data.get("password")
            User.objects.create_user(username=username, password=password)
            print("數據庫保存成功")
            return redirect("/log_in/")
        else:
            errors = login_form.errors # 字典類型,鍵是字段名,值是一個存着所有錯誤信息的列表 莫版中用{{ errors.字段名.0 }}
            # print(type(login_form.errors))# <class 'django.forms.utils.ErrorDict'>
            # login_form.errors={"user":["小於5位","不是數字"],"pwd":["",""]}
            
            error_all = errors.get("__all__")  #全局鈎子的錯誤信息保存在了鍵是 __all__ 的值的列表中,在模版語言中用{{ error_all.0 }}
            print(error_all)
            return render(request, "form_reg.html", {"errors": errors, "error_all":error_all, "login_form": login_form}) else:
   login_form
= LoginForm() # form組件的實例對象 未綁定表單實例 GET請求時渲染出input標簽
     return render(request, "form_reg.html", {"login_form": login_form})

 

 

回到頂部

模版

 

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <!-- 新 Bootstrap 核心 CSS 文件 -->
    <link rel="stylesheet" href="//cdn.bootcss.com/bootstrap/3.3.5/css/bootstrap.min.css">
    <style>
        .container{
            margin-top: 100px;

        }
    </style>
</head>
<body>


<div class="container">
    <div class="row">
        <div class="col-md-6">

            <form action="/login/" method="post"> {% csrf_token %} <div class="form-group">
                    <label for="user">user</label> {{ login_form.user }} <span>{{ errors.user.0 }}</span>
                  </div>
                  <div class="form-group">
                    <label for="pwd">pwd</label> {{ login_form.pwd }} <span>{{ errors.pwd.0 }}</span>
                  </div>
                   <div class="form-group">
                    <label for="gender">gender</label> {{ login_form.gender }}<span>{{ error_all.0 }}</span>
                  </div>

                 <p>{{ login_form.usersss }}</p>

                  <button type="submit" class="btn btn-default">Submit</button>
                </form>
            <hr>

{# <form action="">#} {# {{ login_form.as_p }}#} {# </form>#} </div> </div> </div> </body> </html>

 

 

Django Form 類詳解

 

綁定的和未綁定的表單實例

綁定的和未綁定的表單 之間的區別非常重要:

  • 未綁定的表單沒有關聯的數據。當渲染給用戶時,它將為空或包含默認的值。
  • 綁定的表單具有提交的數據,因此可以用來檢驗數據是否合法。如果渲染一個不合法的綁定的表單,它將包含內聯的錯誤信息,告訴用戶如何糾正數據。

 

字段詳解

 

Widgets

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

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

 

字段的數據

不管表單提交的是什么數據,一旦通過調用is_valid() 成功驗證(is_valid() 返回True),驗證后的表單數據將位於form.cleaned_data 字典中。這些數據已經為你轉換好為Python 的類型。

注:此時,你依然可以從request.POST 中直接訪問到未驗證的數據,但是訪問驗證后的數據更好一些。

在上面的聯系表單示例中,is_married將是一個布爾值。類似地,IntegerField 和FloatField 字段分別將值轉換為Python 的int 和float

 

表單字段詳細參考:http://blog.csdn.net/qq_14898613/article/details/61617007

 

 

使用表單模版

 

表單渲染的選項

 

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

  • {{ form.as_table }} 以表格的形式將它們渲染在<tr> 標簽中
  • {{ form.as_p }} 將它們渲染在<p> 標簽中
  • {{ form.as_ul }} 將它們渲染在<li> 標簽中

注意,你必須自己提供<table> 或<ul> 元素。

{{ form.as_p }}會渲染如下:

<form action="">
    <p>
        <label for="id_username">Username:</label> 
        <input id="id_username" maxlength="100" name="username" type="text" required="">
    </p>


    <p>
        <label for="id_password">Password:</label> 
        <input id="id_password" maxlength="100" name="password" placeholder="password" type="password" required="">
    </p>


    <p>
        <label for="id_telephone">Telephone:</label> <input id="id_telephone" name="telephone" type="number" required="">
    </p>


    <p>
        <label for="id_email">Email:</label> <input id="id_email" name="email" type="email" required="">
    </p>


    <p>
        <label for="id_is_married">Is married:</label> <input id="id_is_married" name="is_married" type="checkbox">
    </p>


    <input type="submit" value="注冊">
</form>
View Code

 

 

 

回到頂部

Form組件的鈎子

 

局部鈎子

 

 def clean_username(self): # 函數名必須已clean_字段名的格式 user = self.cleaned_data.get("username") if not User.objects.filter(username=user): if not user.isdigit(): if re.findall(r"^[A-Za-z0-9_\-\u4e00-\u9fa5]+$",user): return user # 通過檢測,原數據返回 self.cleaned_data.get("username") else: raise ValidationError('用戶名存在非法字符') # 沒通過檢測拋出錯誤,必須用ValidationError else: raise ValidationError("用戶名不能為純數字") else: raise ValidationError("該用戶名已存在")

 

全局鈎子

 

 def clean(self): # 必須命名為clean # 判斷是否都通過檢測,都不為None if self.cleaned_data.get("password") and self.cleaned_data.get("check_pwd"): if self.cleaned_data.get("password") == self.cleaned_data.get("check_pwd"): return self.cleaned_data # 如果兩次密碼相同,返回干凈的字典數據 else: raise ValidationError("輸入密碼不一致") # 沒通過檢測返回異常信息 else: return self.cleaned_data

 

 

回到頂部

form組件補充

 

1.Django內置字段

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類型
    ...
View Code

2.Django內置插件

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
View Code

3.常用選擇插件

# 單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
# )
View Code

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM