????表單的作用是實現網頁上的數據交互,用戶在網站輸入數據信息,提交到網站服務器進行處理。用戶表單是web開發的一項基本操作,Django的表單功能有Form類實現,主要分為兩種:django.forms.Form和django.forms.ModelForm。前者是一個基礎的表單。后者是在前者的基礎結果模型所生成的數據表單。
基礎表單
? ? 傳統表單生成方式是在模板文件中編寫HTML代碼實現,在HTML語言中,表單由<form>標簽實現。表單生成方式如下:
<!DOCTYPE html>
<html>
<body>
? ? <form action="" method="post">
? ????? First name:<br>
????????<input type="text" name="firstname" value="Mickey"><br>
????????Last name:<br>
????????<input type="text" name="lastname" value="Mouse">
????????<input type="submit" value="Submit">
????</form>
</body>
</html>
一個完整的表單有4個主要組成部分:提交地址、請求方式、元素控件、提交按鈕。說明如下:
1.提交地址用于設置用戶提交的表單數據應由那個URL來接受和處理,控件<form>的屬性action決定。當用戶想服務器提交數據時,若屬性action為空,則調教的數據應由當前的URL來接受和處理。否則網頁會跳轉到屬性action所指向的URL地址。
2.請求方式用于設置表單的提交方式,通常是get請求或post請求,由控件<form>的屬性method決定。
3.元素控件是提供用戶輸入數據信息的輸入框。由HTML的<input>控件實現,其控件屬性type用于設置輸入框的類型,常用的輸入框類型有文本框、下拉框、復選框
4.提交按鈕提供用戶提交數據到服務器,按鈕也由HTML的<input>控件實現,但該按鈕具有一定的特殊性,因此不歸納到元素空間的 范圍內。
? ? 在模板文件中,直接編寫表單是一種較為簡單的實現方式,如果過表單元素較多,會在無形之中增加模板的代碼量,這樣對日后的維護和更新帶來不便。為了簡化表單的實現過程和提高表單的靈活性,Django提供了完善的表單功能。
? ? 在項目的index中添加空白文件form.py,改文件主要用于編寫表單的實現功能。文件夾可自行命名:同事在文件夾templates中添加模板文件data_form.html,改文件用于將表單的數據顯示到網頁上。最后在文件form.py, views.py, data_form.html添加一下代碼:
# form.py代碼,定義ProductForm表單對象
from django import forms
from .models import *
class ProductForm(forms.Form):
????name = forms.CharField(max_length=20, label='名字',)
????weight = forms.CharField(max_length=50, label='重量')
????size = forms.CharField(max_length=50, label='尺寸')
????choices_list = [(i+1, v['type_name']) for i,v in enumerate(Type.objects.values('type_name'))]
????type = forms.ChoiceField(choices=choices_list, label='產品類型')
# views.py 代碼 將表單 ProductForm實例化并將其傳遞到末班中生成網頁內容
from django.shortcuts import render
from .form import *
def index(request):
????product = ProductForm()
????return render(request, 'data_form.html',locals())
# data_form.html代碼, 將表單對象的內容顯示在網頁上
<!DOCTYPE html>
<html lang="en">
<head>
????<meta charset="UTF-8">
????<title>Title</title>
</head>
<body>
{% if product.errors %}
????<p> 數據出錯啦,錯誤信息:{{ product.errors }}. </p>
????{% else %}
????<form action="" method="post">
????????{% csrf_token %}
????????<table> {{ product.as_table }} </table>
????????<input type="submit" value="提交">
????????{{ product.type.type }}
????????</form>
????????{% endif %}
</body>
</html>
? ? 上述代碼演示了Django內置表單功能的使用方法,主要由form.py,views.py,data_form.html共同實現,說明如下:
? ? 1.在form.py中定義表單ProductForm,表單以類的形式表示,在表單中定義了不同類型的雷屬性,這些屬性在表單中稱為表單字段,每個表單字段代表HTML里面的一個控件,這是表單的基本組成單位。
????2.在views.py中導入form.py所定義的ProductForm類,在視圖函數index中對ProductForm實例化生成對象product,再講對象product傳遞給模板data_form.html
????3.模板data_form.html將對象product以HTML的<table>的形式展示在網頁上。
表單定義
? ? Django的表單功能主要是通過定義表單類,再由類的實例化生成HTML的表單元素控件,這樣可以在模板中減少HTML的硬編碼每個HTML的表單元素控件由表單字段來決定,代碼如下:
# 表單類ProductForm的表單字段name
name = forms.CharField(max_leng=20, label='名稱',)
# 表單字段name所生成的HTML元素控件
<tr>
<th><label for="id_name"> 名稱:</label><th>
<td><input type="text" name="name" id="id_name" required maxlength="20"></td>
</tr>
? ? 從表單字段轉換HTML元素控件可以發現:
? ? 1.字段那么的參數label將轉化成HTML的標簽<label>
????2.字段name的forms.CharField 類型轉換成HTML的<input type="text"> 控件,標簽<input>是一個輸入框控件,type="text"代表當前輸入框為文本輸入框,參數type用于設置輸入框的類型。
????3.字段那么的命名轉換成<input>控件的參數name, 表單字段的參數max_length將轉換成<input>控件的參數required maxlength.
除了上述表單字段外,Django還提供多種內置的表單字段,如需要了解可去官網查詢相關資料。
模型與表單
? ? 數據表單是將模型的字段轉換成表單的字段,再從表單的字段生成HTML的元素控件,這是日常開發中常用的表單之一。接下來重點說明ModelForm實現表單數據與模型數據之間的交互開發。
? ? 首先在文件form.py中定義表單ProductModelForm,該表單繼承自父類forms.ModelForm。代碼如下:
from django import forms
from .models import *
from django.core.exceptions import ValidationError
class ProductModelForm(forms.ModelForm):
????# 添加模型外的表單字段
????productId = forms.CharField(max_length=20, label='產品序號', initial='NO1')
????# 模型與表單設置
????class Meta:
????????# 綁定模型
????????model = Product
????????# fields 屬性是設置轉換字段,'__all__'是將全部模型字段轉換成表單字段
????????# fields = '__all__'
????????fields = ['name','weight','size','type']
????????# exclude是禁止模型字段轉換表單字段
????????exclude = []
????????# labels設置HTML元素控件的label標簽
????????abels = { 'name': '產品名稱', 'weight': '重量', 'size': '尺寸', 'type': '產品類型' }
????????# 定義widgets,設置表單字段的CSS樣式
????????widgets = { 'name': forms.widgets.TextInput(attrs={'class': 'c1'}), }
????????# 定義字段的類型,一般情況下模型的字段會自動轉換成表單字段
????????field_classes = { 'name': forms.CharField }
????????# 幫助提示信息 help_texts = { 'name': '' }
????????# 自定義錯誤信息
????????error_messages = {
????????????????????????????????????????# __all__設置全部錯誤信息
????????????????????????????????????????'__all__':{'required': '請輸入內容', 'invalid': '請檢查輸入內容'},
????????????????????????????????????????# 設置某個字段錯誤信息
????????????????????????????????????????'weight': {'required': '請輸入重量數值', 'invalid': '請檢查數值是否正確'} }
# 自定義表單字段weight的數據清洗
def clean_weight(self):
????# 獲取字段weight的值
????data = self.cleaned_data['weight']
????return data+'g'
? ? 上述代碼中,表單類ProdectModelForm可分為三大部分:添加模型外的表單字段、模型與表單設置和自定義表單字段weight的數據清洗函數,說明如下:
? ? 1.添加模型外的表單字段是在模型已有的字段下添加額外的表單字段。
? ? 2.模型與表單設置是將模型的字段轉換成表單字段,由類meta的屬性實現兩者的字段轉換。
? ? 3.自定義表單字段weight的數據清洗函數只適用于字段weight的數據清洗。
類Meta的屬性及說明
? ? 模型字段轉換成表單字段主要在類Meta中實現。
model:? 必需屬性,用于綁定Model對象。
fields:? ?必需屬性,設置模型內那些字段轉換成表單字段。屬性值為'__all__'代表整個模型的字段,若設置一個或多個,使用列表或元組的數 據格式表示,列表或元組里的元素是模型的字段名。
exclude:? 可選屬性,與fields相反。
labels:? 可選屬性,設置表單字段里的參數label。屬性值以字典表示,字典里ID鍵是模型的字段。
widgets:可選屬性,設置表單字段的參數widget
field_classes:? 可選屬性,將模型的字段重新定義為表單字段類型,默認情況下,模型字段類型會自動轉換為表單字段類型。
help_texts:? 可選屬性,設置表單字段里的參數help_text.
error_messages:? 可選屬性,設置表單字段里的參數error_messages.
重寫初始化函數__init__()
class ProductModelForm(forms.ModelForm):
# 重寫ProductModelForm類的初始函數__init__
????def __init__(self, *args, **kwargs):
????????super(ProductModelForm, self).__init__(*args, **kwargs)
????????# 設置下拉框的數據
????????type_obj = Type.objects.values('type_name')
????????choices_list = [(i + 1, v['type_name']) for i, v in enumerate(type_obj)]
????????self.fields['type'].choices = choices_list
????????# 初始化字段name
????????self.fields['name'].initial = '我的手機'