<学习笔记>从零开始自学Python-之-web应用框架Django( 八)Django表单
? ? ? ? HTML 表單是交互式網站的基本組成部分,用戶提交信息、搜索內容、與后臺數據交互都要用到表單。
1、從請求對象中獲取數據
? ? ? ? view視圖函數的第一個參數都是 request,這個request就是請求獲得的HttpRequest對象。里面包含中有一些關于當前所請求 URL 的信息,如下圖
| request.path | 完整的路徑,不含域名,但是包 含前導斜線 | “/hello/” |
| request.get_host() | 主機名(即通常所說的“域名”) | “127.0.0.1:8000”或www.newweb.com |
| request.get_full_path() | 包含查詢字符串(如果有的話) 的路徑 | “/hello/?print=true” |
| request.is_secure() | 通過 HTTPS 訪問時為 True,否 則為 False | True 或 False |
2、關于請求的其他信息
? ? ? ? request.META 的值是一個 Python 字典,包含請求的所有 HTTP 首部,例如用戶的 IP 地址和用戶代理(user agent,通常是 Web 瀏覽器的名稱和版本)。
? ? ? ? 注意,具體包含哪些首部取決于用戶發送了什么首部,以及 Web 服務器返回了什么首部。
這個字典中常見的幾個鍵有:
? HTTP_REFERER:入站前的 URL(可能沒有)。(注意,要使用錯誤的拼寫,即 REFERER。)
? HTTP_USER_AGENT:瀏覽器的用戶代理(可能沒有)。例如:"Mozilla/5.0 (X11; U; Linux i686; frFR; rv:1.8.1.17) Gecko/20080829 Firefox/2.0.0.17"。
? REMOTE_ADDR:客戶端的 IP 地址,例如 "12.345.67.89"。(如果請求經由代理,這個首部的值可能是一 組 IP 地址,以逗號分隔,例如 "12.345.67.89,23.456.78.90"。)
注意,因為 request.META 是個普通的 Python 字典,所以嘗試訪問不存在的鍵時,拋出 KeyError 異常。 (HTTP 首部是外部數據,即由用戶的瀏覽器提交,因此不能完全相信,當某個首部為空或不存在時,應該讓應用程序優雅失敗。)為了處理未定義的鍵,應該使用 try/except 子句,或者 get() 方法:
# 用try語句 def ua_display_good1(request):try:useragent = request.META['HTTP_USER_AGENT']except KeyError:useragent = 'unknown'return HttpResponse("Your browser is %s" % useragent)# 用get方法 def ua_display_good2(request):useragent = request.META.get('HTTP_USER_AGENT', 'unknown')return HttpResponse("Your browser is %s" % useragent)也可以編寫一個簡單的視圖,顯示 request.META 中的所有信息,以便查閱。
def display_meta(request):values = request.META.items()valueshtml = []for k, v in values:html.append('<tr><td>%s</td><td>%s</td></tr>' % (k, v))return HttpResponse('<table>%s</table>' % '\n'.join(html))3、用表單實現查詢功能
? ? ? ? 除了關于請求的基本元數據之外,HttpRequest 對象還有兩個屬性包含用戶提交的信息:request.GET 和 request.POST。這兩個屬性的值都是類似字典的對象,分別用于獲取 GET 和 POST 數據。POST 數據一般由 HTML 表單提交,而 GET 數據既可以來自表單,也可以來自頁面 URL 中的查詢字符串。
? ? ? ? 我們利用request.GET 和 request.POST就可以實現前后端之間的通信,讓用戶提交的信息傳遞給服務器,服務器進行響應。
? ? ? ? 我們前面的案例中說到可以用url傳輸信息給后端,但那不是個好辦法,現在我們改用表單傳輸數據,實現查詢功能。我們先在之前的 'notice/'? url 對應的 class3.html 增加一個查詢表單(純屬偷懶,表單應該放到頁面合適的地方去)
<form action="/search/" method="get"><h3>根據姓名查找同學</h3> <input type="text" name="chaxun"> <input type="submit" value="查詢"> </form>這里 method = ‘get’表示請求的方法為? get
<h3>這一行是標題,告訴用戶這個表單是干嘛的,應該填什么數據,可要可不要
第一個input 的 name='chaxun' 這是后面我們找數據是要用到的標簽名稱
第二個input 的 type = 'submit' 表示這是一個提交按鈕,value='查詢' 表示它在頁面上顯示為“查詢”
看一下頁面:
?然后我們來寫個視圖函數 chaxun1
def chaxun1(request):studentName = request.GET['chaxun']s = Student.objects.get(name=studentName)return HttpResponse('你要查詢的{}同學信息如下:姓名:{},年齡{},性別{},成績{},武力值{}'.format(s.name,s.name,s.age,s.sex,s.score,s.skill))然后我們在上面的文本框中輸入 “黃蓉”,點擊查詢按鈕,得到如下結果:
?4、改進表單
? ? ? ?上面這個表單雖然實現了我們預期的功能,但是還不完善。比如如果用戶提交的是個空表單怎么辦,如果用戶提交的信息數據庫里查不到怎么辦,我們不能總是報錯啊,現在我們來著手改進這個表單:
if request.GET and request.GET['chaxun']: #確保GET方法獲得了值,并且'chaxun'標簽(就是那個提交查詢內容的輸入框)不為空studentName = request.GET['chaxun']try: #確保要查詢的數據存在s = Student.objects.get(name=studentName)result = '你要查詢的{}同學信息如下:姓名:{},年齡{},性別{},成績{},武力值{}'.format(s.name,s.name,s.age,s.sex,s.score,s.skill)context['result']=resultexcept:context['result']='查無此人' #如果查不到,顯示“查無此人”并返回同一個頁面return render(request,'class3.html',context=context,status=200)else: #如果輸入為空,曾刷新頁面,重新填寫return render(request, 'class3.html')這樣改造后,我們再查詢頁面,就可以直接看到結果了,輸入空值則會返回當前頁面繼續填寫
5、Django的表單類
? ? ? ? 用戶在填寫表單的時候,誰也不知道用戶會寫些什么,為了數據能夠按規范填寫,就需要對用戶的填寫行為進行約束,也就是表單的驗證。我們當然可以自己手動去寫這些驗證方法,不過Django已經貼心地為我們準備好了內置的表單庫,django.forms,它能處理從顯示 HTML 表單到驗證的大多數問題,即開即用。
? ? ? ? 我們用一個例子來演示一下這個表單類怎么用。比如上面那個查詢功能,我們現在用forms表單類把它集成實現。
? ? ? ? 首先新建一個forms.py文件(當然也可以直接寫在views.py,不過一般Django風格都是給forms單獨一個文件)我們定義一下我們需要的字段。這里的字段其實是顯示在前端給用戶看的,所以想要讓用戶輸入什么字段,就在這里定義,比如我們這里打算讓用戶可以通過?姓名、年齡 和 成績這三個條件來查詢:
from django import forms #注意這里要從django引入forms庫 class chaxunForm(forms.Form): #定義一個查詢類#這里label就是前端顯示的輸入框的提示文字,max_length是輸入的最大長度,#required=False是允許這個值為空,因為我們期望的是通過每個條件單獨都可以查詢name = forms.CharField(label="名字",max_length=10,required=False) #這里可以定義輸入數值的大小,用max_value 和 min_value 參數來設定上下限age = forms.IntegerField(label="年齡",required=False,max_value=100,min_value=10)score = forms.IntegerField(label="成績",required=False)為了方便演示,我們另外寫了個HTML頁面文件 chaxun.html,反正用模板繼承很方便
{% extends "base.html" %} {% block title %}武俠三班的小窩{% endblock %}{% block main %} <h1>查詢頁面,在這里可以查找你想了解的同學</h1><form action="" method="post">{% csrf_token %}<h3>根據條件查找同學</h3>{{form}}<input type="submit" value="查詢"> </form><P>{% for result in results %} <div>{{result}}</div>{% endfor %} </P>{% endblock %}注意這里頁面上的輸入框不用我們自己手動寫了,form類會自動把自定義的字段轉成input輸入框? 然后我們去views.py調用這個類,
from classManage.forms import chaxunForm ........ #其他代碼 ........ def chaxun4(request):context={}form=chaxunForm(request.POST) if request.method == 'POST': #這里要注意確認一下方法為POSTform = chaxunForm(request.POST) #實例化一個我們在forms.py里面定義的chaxunForm類context['form']=form #把form實例賦值給字典的 'form',方便前端調用results = []if form.is_valid(): #確保form的數據有效,這個驗證工作forms類幫我們做了stuName = form.cleaned_data.get('name') #cleaned_data是經過清洗的數據 stuAge = form.cleaned_data.get('age')print(stuAge)if stuName:#名字一般是唯一的,但是為了上下統一用一個函數比較方便,我們統統用filter,而不是get,然后把數據放到一個列表中去遍歷stus=Student.objects.filter(name=stuName) elif stuAge:stus=Student.objects.filter(age=stuAge)elif stuScore: stus=Student.objects.filter(score=stuScore)else:passfor s in stus:result = '你要查詢的{}同學信息如下:姓名:{},年齡{},性別{},成績{},武力值{}'.format(s.name,s.name,s.age,s.sex,s.score,s.skill)results.append(result)print('postresult:',results)context['results']=resultsreturn render(request,'class3.html',context=context,status=200)else:form = chaxunForm()context['form']=form #把form對象整個賦值給字典的 'form'方便前端調用return render(request,'chaxun.html',context=context,status=200)我們去訪問頁面?http://127.0.0.1:8000/cha/ 看看效果
可以看到出現了 名字、年齡、成績 三個查詢框,我們任意填其中一個,實現查詢功能
?
?我們測試一下forms的驗證效果,我們在年齡框里面輸入漢字,發現根本不給輸入,然后我們在年齡這里輸入數字5,點擊查詢后發現它提示我數字必須大于10:
當然這里這個提示不太美觀,可以自定義來定制驗證信息。總之,forms類可以幫我們進行數據審查,比如如果我們定義了一個forms類的email字段,它會自動審查輸入是否為一個email格式,這真的大大簡化了我們的工作啊。
所以我們一般做登錄、注冊表單或者信息提交表單的時候,用這個forms類真的很方便。?
總結
以上是生活随笔為你收集整理的<学习笔记>从零开始自学Python-之-web应用框架Django( 八)Django表单的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: winedt103系统找不到指定文件_l
- 下一篇: 自强不息系列之Python 线性查找