單純從前端的html來說,表單是用來提交數據給服務器的,不管后臺的服務器用的是Django還是PHP語言還是其他語言。只要把input標簽放在form標簽中,然后再添加一個提交按鈕(submit),那么以后點擊提交按鈕,就可以將input標簽中對應的值提交給服務器了。
Django中的表單:
Django中的表單豐富了傳統的HTML語言中的表單。在Django中的表單,主要做以下兩件事:
<1> 渲染表單模板。
<2> 表單驗證數據是否合法
以生成'留言板'網頁為示例:
步驟<1> 新建'front app',新建'forms'
# forms
# 總覽一下,操作方法與'模型'類似
from django import forms
class MessageBoardForm(forms.Form): # 繼承Form類
title=forms.CharField(max_length=10,min_length=2)
content=forms.CharField(widget=forms.Textarea)# 使用widget(組件)指定'Textarea'類型
email=forms.EmailField()
reply=forms.BooleanField(required=False)# reply字段通過'required'參數取值,表示'可選','可不選'
步驟<2> '服務端'加載'MessageBoardForm'
# front.views
from django.shortcuts import render
from django.views.generic import View
from .forms import MessageBoardForm
# FormView用來處理'get'和'post'請求
class FormView(View):
def get(self,request):
# 生成空表單并傳遞context
# 這個form對象包含了不少方法和屬性,可以了解
form=MessageBoardForm()
context={
'form':form
}
return render(request,'index.html',context=context)
步驟<3> 前端模板的渲染并映射url
# index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Message Board</title>
</head>
<body>
<form action="" method="post">
<table>
{{ form.as_table }} # 這里使用form對象的as_table渲染表單
<tr>
<td></td>
<td>
<input type="submit" value="提交"> # 定義'提交'按鈕,發送數據
</td>
</tr>
</table>
</form>
</body>
</html>
'''
實際開發中,很少用到form.as_table,比如想插入CSS之類的樣式,這里要怎么破...
'''
# urls
from django.urls import path
from front import views
urlpatterns = [
path('', views.FormView.as_view()),
]
啟動服務,刷新網頁,看看效果(每個'字段'會'自動'添加':'符號)
通過試驗,即使后端的'post'方法沒有定義,但是前端依然對'字段'作了限制
比如'content'字段不能為空,'email'字段的格式'隨便寫'也是不能通過的
(請不要'圖樣圖森破',以為'后端'就不用對'字段'作限制了...原因自己想...)
? 小小修改一下'forms.py',變更模板的標簽(通過'label'設置中文標簽)
# forms
from django import forms
class MessageBoardForm(forms.Form):
# 通過label參數設置中文標簽
title=forms.CharField(max_length=10,min_length=2,label='標題')
content=forms.CharField(widget=forms.Textarea,label='內容')
email=forms.EmailField(label='郵箱')
reply=forms.BooleanField(required=False,label='回復')
步驟<4> 后端'post'方法編寫:
# views
from django.shortcuts import render
from django.views.generic import View
from .forms import MessageBoardForm
from django.http import HttpResponse
class FormView(View):
def get(self,request):
......
return render(request,'index.html',context=context)
def post(self,request):
# 這里依然涉及form對象的一些屬性和方法,有空可以去了解(is_valid和cleaned_data經常搭配使用)
form=MessageBoardForm(request.POST) # 接收POST傳過來的'類字典對象'
if form.is_valid(): # 驗證是否可用
title=form.cleaned_data.get('title') # 利用cleaned_data屬性獲取對應的字段
content=form.cleaned_data.get('content')
email=form.cleaned_data.get('email')
reply=form.cleaned_data.get('reply')
# 終端獲取前端傳過來的數據
print('*'*40)
print(title)
print(content)
print(email)
print(reply)
print('*'*40)
return HttpResponse('留言板回復成功!!!')
else:
print(form.errors) # 如果用戶發送的字段驗證失敗,'終端打印錯誤信息'
return HttpResponse('fail!')
'''
<ul class="errorlist"><li>content<ul class="errorlist"><li>This field is required.</li></ul></li><li>title<ul class="errorlist"><li>This field is required.</li></ul></li><li>email<ul class="errorlist"><li>This field is required.</li></ul></li></ul>
'''
異常的處理:
errors屬性返回的'信息'并不友好,查看type(form.errors)
# class 'django.forms.utils.ErrorDict' ,errors實質就是'ErrorDict'的一個實例,查看源碼,我們調用get_json_data()返回更加友好的錯誤信息:
class FormView(View):
......
else:
# {'content': [{'message': 'This field is required.', 'code': 'required'}], 'title': [{'message': 'This field is required.', 'code': 'required'}], 'email': [{'message': 'This field is required.', 'code': 'required'}]}
print(form.errors.get_json_data())
return HttpResponse('fail!')
'''
顯然看起來更加清楚了
'''
進一步的改進:使用中文'自定義'出錯內容
# forms
from django import forms
class MessageBoardForm(forms.Form):
# 通過 error_messages 參數自定義'出錯信息'
title=forms.CharField(max_length=10,min_length=2,label='標題',
error_messages=dict(min_length='字段不能少于2個字符'))
content=forms.CharField(widget=forms.Textarea,label='內容',
error_messages=dict(required='必須輸入content字段'))
email=forms.EmailField(label='郵箱',error_messages=dict(required='必須輸入email字段'))
reply=forms.BooleanField(required=False,label='回復')
'''
{'content': [{'message': '必須輸入content字段', 'code': 'required'}], 'email': [{'message': '必須輸入email字段', 'code': 'required'}], 'title': [{'message': 'This field is required.', 'code': 'required'}]}
'''
使用純前端的實例(例如前端不再使用form.as_table):
# forms
from django import forms
class MessageBoardForm(forms.Form):
# 這里傳遞的key不僅僅只有'required',比如還有'invalid'
email=forms.EmailField(label='郵箱',error_messages=dict(required='必須輸入email字段'))
price=forms.FloatField(label='價格',error_messages=dict(invalid='請輸入正確的浮點類型'))
# views
from django.shortcuts import render
from django.views.generic import View
from .forms import MessageBoardForm
from django.http import HttpResponse
from django.forms.utils import ErrorDict
class FormView(View):
# 不再傳遞context=form,直接加載前端表單
def get(self,request):
return render(request,'index.html')
def post(self,request):
form=MessageBoardForm(request.POST)
if form.is_valid():# 字段的驗證,在調用is_valid()的時候,就會被驗證
price=form.cleaned_data.get('price')
return HttpResponse('數據提交成功!!!')
else:
print(form.errors.get_json_data()) # 最終都是調用get_json_data()方法
return HttpResponse('數據提交失敗!')
# html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Message Board</title>
</head>
<body>
<form action="" method="post">
<label> 郵箱:
<input type="text" name="email">
</label>
<label> 價格:
<input type="text" name="price">
</label>
<input type="submit" value="submit">
</form>
</body>
</html>
重啟服務,故意輸錯,看看終端的效果
'''
{'price': [{'message': '請輸入正確的浮點類型', 'code': 'invalid'}], 'email': [{'message': '必須輸入email字段', 'code': 'required'}]}
'''
注意:由于前端使用了純html語言,前端界面不會再對郵箱字段的'有效性'進行驗證,而我們之前使用form.as_table是可以從前端對字段的'有效性'進行驗證的!