Django之視圖,內容包括 視圖,HttpReqeust對象,ajax請求。其中,視圖 包括 視圖函數的使用,url匹配的過程,錯誤視圖處理,捕捉url參數,普通登錄案例;HttpReqeust對象 包括 屬性,QueryDict對象;ajax請求 包括 python和ajax結合使用,ajax同... ...
Django1.8.2中文文檔:Django1.8.2中文文檔
視圖
視圖的功能
接收請求,進行處理,與M和T進行交互,返回應答。
返回html內容 HttpResponse,也可能重定向 redirect,還可以返回json數據。
視圖函數的使用
使用
1)定義視圖函數
request參數必須有。是一個HttpRequest類型的對象。參數名可以變化,但最好不要更改。
2)配置url
建立url和視圖函數之間的對應關係。
url配置的過程
- 1)在項目的urls文件中包含具體應用的urls文件,在具體應用的urls文件中包含具體url和視圖的對應關係。
- 2)url配置項是定義在一個名叫urlpatterns的列表中,其中的每一個元素就是一個配置項,每一個配置項都調用url函數。
如下
test1000/url.py
urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^', include('booktest.urls')), # 包含booktest應用中的路由文件 ]
booktest/url.py
urlpatterns = [ url(r'^index/', views.index), # 顯示圖書信息 url(r'^create/', views.create), # 添加一本書籍 url(r'^delete(\d+)/', views.delete), # 刪除一本書籍 ]
url匹配的過程
url匹配圖解
匹配示例:
url:http://127.0.0.1:8000/aindex?a=1
- 1) 去除功能變數名稱和後面的參數,剩下/aindex,再把前面的/去掉,剩下aindex
- 2) 拿aindex先到項目的url.py文件中進行從上到下的匹配,匹配成功之後執行後面對應的處理動作,就是把匹配成功的部分a字元去除,然後拿剩下的部分index到應用的urls.py文件中再進行從上到下的匹配。
- 3) 如果匹配成功則調用相應的視圖產生內容返回給客戶端。如果匹配失敗則產生404錯誤。
錯誤視圖
當我們在開發時,可以設置settings文件裡面的DEBUG=True,但當我們要上線產品時,應該設置為False,否則會把網站的信息暴露出來。
開發時:
DEBUG = True
ALLOWED_HOSTS = []
要上線時:
DEBUG = True ALLOWED_HOSTS = ['*']
404: 找不到頁面。可能原因
- a)url沒有配置
- b)url配置錯誤
- c)瀏覽器url’/’問題
500: 伺服器端的錯誤。可能原因
- a)視圖出錯
自定義404頁面
修改為上線模式後,在templates下新建並編寫一個404.html,即可。
在使用這個頁面的過程中,Django會傳過來一個模板變數,{{ request_path }},表示用戶請求路徑。
500錯誤頁面同理。
捕捉url參數
進行url匹配時,把所需要的捕獲的部分設置成一個正則表達式組,這樣django框架就會自動把匹配成功後相應組的內容作為參數傳遞給視圖函數。
1)位置參數
位置參數,參數名可以隨意指定
2)關鍵字參數:在位置參數的基礎上給正則表達式組命名即可。
?P<組名>
關鍵字參數,視圖中參數名必須和正則表達式組名一致.
捕獲url參數示例:
url(r'^delete(\d+)/', views.delete), # 捕獲url參數:位置參數 url(r'^delete(?P<bid>\d+)/', views.delete), # 捕獲url參數:關鍵字參數 def delete(request, bid): """刪除一本書籍""" # 1.獲取書籍對象 book = models.BookInfo.objects.get(id=bid) # 2.刪除書籍 book.delete() # 3.重定向 return redirect('/index')
註意,使用關鍵字參數時,視圖中的參數名應該和正則表達式中的參數名一致
普通登錄案例
普通登錄案例項目分析
1)顯示出登錄頁面
- a)設計url,通過瀏覽器訪問 http://127.0.0.1:8000/login 時顯示登錄頁面。
- b)設計url對應的視圖函數login。
- c)編寫模板文件login.html。
url | 視圖 | 模板文件 |
/login | login | login.html |
2)登錄校驗功能
- a)設計url,點擊登錄頁的登錄按鈕發起請求http://127.0.0.1:8000/login_check時進行登錄校驗。
- b)設計url對應的視圖函數login_check。
- 接收表單提交過來的數據。
- 進行登錄校驗,若用戶名密碼正確則跳轉到登錄成功頁。若失敗在跳轉到登錄頁面。
- c)登錄成功後跳轉到首頁。
url | 視圖 | 模板文件 |
/login_check | login_check | 無 |
普通登錄示例代碼
定義login.html頁面
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Login</title> <meta name="viewport" content="width=device-width, initial-scale=1"> </head> <body> <form action="/login_check/" method="post"> <label for="username">用戶: <input type="text" id="username" name="username"> </label><br /> <label for="password">密碼: <input type="password" id="password" name="password"> </label><br /> <input type="submit" value="登錄"> </form> </body> </html>index.html
編寫login函數
def login(request): """登錄處理函數""" return render(request, "booktest/login.html")
配置login和login_check路由
url(r'^login/$', views.login),
url(r'^login_check/$', views.login_check),
編寫login_check函數
def login_check(request): # 1.獲取用戶名和密碼 username = request.POST.get("username") password = request.POST.get("password") # 2.進行校驗 # 3.返回應答 if username == "yifchan" and password == "yifchan": return redirect("/index") else: return HttpResponse("賬號或密碼錯誤")
HttpReqeust對象
伺服器接收到http協議的請求後,會根據報文創建HttpRequest對象,這個對象不需要我們創建,直接使用伺服器構造好的對象就可以。
視圖的第一個參數必須是HttpRequest對象,即request,在django.http模塊中定義了HttpRequest對象的API。
屬性
下麵除非特別說明,屬性都是只讀的。
path | 一個字元串,表示請求的頁面的完整路徑,不包含功能變數名稱和參數部分。 |
method | 一個字元串,表示請求使用的HTTP方法,常用值包括:'GET'、'POST'。 在瀏覽器中給出地址發出請求採用get方式,如超鏈接。 在瀏覽器中點擊表單的提交按鈕發起請求,如果表單的method設置為post則為post請求。 |
encoding |
一個字元串,表示提交的數據的編碼方式。如果為None則表示使用瀏覽器的預設設置,一般為utf-8。 這個屬性是可寫的,可以通過修改它來修改訪問表單數據使用的編碼,接下來對屬性的任何訪問將使用新的encoding值。 |
GET | QueryDict類型對象,類似於字典,包含get請求方式的所有參數。 |
POST | QueryDict類型對象,類似於字典,包含post請求方式的所有參數。 |
FILES | 一個類似於字典的對象,包含所有的上傳文件。 |
COOKIES | 一個標準的Python字典,包含所有的cookie,鍵和值都為字元串。 |
session | 一個既可讀又可寫的類似於字典的對象,表示當前的會話,只有當Django 啟用會話的支持時才可用,詳細內容見"狀態保持"。 |
QueryDict對象
- 定義在django.http.QueryDict
- HttpRequest對象的屬性GET、POST都是QueryDict類型的對象
- 與python字典不同,QueryDict類型的對象用來處理同一個鍵帶有多個值的情況
方法get()
根據鍵獲取值
如果一個鍵同時擁有多個值將獲取最後一個值
如果鍵不存在則返回None值,可以設置預設值進行後續處理
dict.get('鍵',預設值) # 可簡寫為 dict['鍵']
方法getlist()
根據鍵獲取值,值以列表返回,可以獲取指定鍵的所有值
如果鍵不存在則返回空列表[],可以設置預設值進行後續處理
dict.getlist('鍵',預設值)
方法dict['鍵']
根據鍵獲取值
和get()方法差不多,但沒有值的時候會報錯;
取QueryDict值示例
from django.http.request import QueryDict q = QueryDict('a=1&b=2&c=3') q['a'] q['b'] q.get('a') q.get('c', default="")
應註意使用[]取值時如果沒有值會報錯,而get只會返回一個none,不會報錯,所以一般使用get;
此外,QueryDict和字典的不同之處在於可以一個key對應多個value,但會取後面的那個value,
想要獲取該key所有的value,可以通過dict.getlist('鍵',預設值)進行獲取。
ajax請求
ajax,即非同步的javascript。在不全部載入某一個頁面部的情況下,對頁面進行局的刷新,ajax請求都在後臺。
圖片,css文件,js文件都是靜態文件。
1)發起ajax請求:jquery發起
2)執行相應的視圖函數,返回json內容
3)執行相應的回調函數。通過判斷json內容,進行相應處理。
python和ajax結合使用
因為要引入jquery,一般對於這些靜態文件,我們會創建static文件,將靜態文件放入裡面,在settings文件裡面進行配置。
STATIC_URL = '/static/' STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static')] # 設置靜態文件的保存目錄
在static文件夾下新建js,css等文件;
在js中引入jquery文件;
編寫ajax_test.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <meta name="viewport" content="width=device-width, initial-scale=1"> <script src="/static/js/jquery-3.3.1.js"></script> <script> $(function () { {# 綁定btnAjax的click事件#} $('#btnAjax').click(function () { $.ajax({ 'url': '/ajax_handle', 'type': 'get', 'datatype': 'json' }).done(function (data) { // 處理後端拿過來的數據 // console.log(data.res); if (data.res == '1') { $('#message').show().html("提示信息"); } }) }) }) </script> <style> #message {display: none;color: red;} </style> </head> <body> <input type="button" id="btnAjax" value="ajax請求"> <div id="message"></div> </body> </html>ajax_test.html
編寫ajax_test函數
def ajax_test(request): """返回ajax頁面""" return render(request, "booktest/ajax_test.html")
設計ajax_test,ajax_handle的url
url(r'^ajax_test/$', views.ajax_test),
url(r'^ajax_handle/$', views.ajax_handle),
編寫ajax_handle處理函數
def ajax_handle(request): """ajax處理函數""" return JsonResponse({"res": 1})
關於ajax調試,可以使用瀏覽器的network視窗,如果出現問題,就到network視窗,點擊出錯的請求,再點擊response,就會有報錯詳情了;
ajax同步和非同步
同步:等別人執行完再執行;
非同步:不管別人有沒有執行完,就執行;
ajax預設是非同步的,即不等ajax請求返回數據,就執行ajax後面的代碼,如果想要實現ajax通過不,可以添加'async': false:
$.ajax({ 'url': '/ajax_handle', 'dataType': 'json', 'async': false, // 同步的ajax請求,預設為True })
ajax預設是非同步的請求
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <meta name="viewport" content="width=device-width, initial-scale=1"> <script src="/static/js/jquery-3.3.1.js"></script> <script> $(function () { // 綁定btnAjax的click事件 $('#btnAjax').click(function () { console.log("1"); $.ajax({ 'url': '/ajax_handle', 'type': 'get', 'datatype': 'json' }).done(function (data) { // 處理後端拿過來的數據 console.log("2"); }) console.log("3"); }) }) </script> <style> #message {display: none;color: red;} </style> </head> <body> <input type="button" id="btnAjax" value="ajax請求"> <div id="message"></div> </body> </html>ajax非同步示例代碼
這個時候,是預設的非同步ajax,就會依次彈出1,3,2;
同步的ajax請求,需要在ajax中添加 'async': false,
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <meta name="viewport" content="width=device-width, initial-scale=1"> <script src="/static/js/jquery-3.3.1.js"></script> <script> $(function () { // 綁定btnAjax的click事件 $('#btnAjax').click(function () { console.log("1"); $.ajax({ 'url': '/ajax_handle', 'type': 'get', 'datatype': 'json', 'async': false, // 同步的ajax請求,預設為True }).done(function (data) { // 處理後端拿過來的數據 console.log("2"); }) console.log("3"); }) }) </script> <style> #message {display: none;color: red;} </style> </head> <body> <input type="button" id="btnAjax" value="ajax請求"> <div id="message"></div> </body> </html>ajax同步示例代碼
這個時候,是同步的ajax,就會依次彈出1,2,3;
ajax登錄案例
編寫login_ajax.html頁面
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Login</title> <meta name="viewport" content="width=device-width, initial-scale=1"> <script src="/static/js/jquery-3.3.1.js"></script> <script> $(function () { // 綁定btnLogin的click事件 $('#btnLogin').click(function () { // 1.獲取用戶輸入的用戶名和密碼 $username = $('#username').val(); $password = $('#password').val(); // 2.攜帶用戶名和密碼,發起ajax請求,login_ajax_check $.ajax({ 'url': '/login_ajax_check/', 'type': 'post', 'data': {'username': $username, 'password': $password}, 'datatype': 'json', }).done(function (data) { // 登錄成功,{'res': 1} // 登錄失敗,{'res': 0} if (data.res == '0') { console.log("res0"); $('#error_message').show() } else { // 登錄成功則跳轉到首頁 console.log("res1"); location.href = '/index'; } }); }) }) </script> <style> #error_message { display: none; color: red; } </style> </head> <body> <div> <label for="username">用戶: <input type="text" id="username" name="username"> </label><br /> <label for="password">密碼: <input type="password" id="password" name="password"> </label><br /> <div id="error_message">賬號名或密碼錯誤</div> <input type="button" id="btnLogin" value="登錄"> </div> </body> </html>login_ajax.html
編寫login_ajax函數
def login_ajax(request): """返回ajax登錄頁面""" return render(request, "booktest/login_ajax.html")
設計login_ajax路由:
url(r'^login_ajax/$', views.login_ajax),
點擊登錄後ajax發送消息給後端路由,
編寫login_ajax_check登錄校驗函數
def login_ajax_check(request): # 1.獲取用戶名和密碼 # 如果是ajax提交的,那麼這裡的get中的值應該和ajax發過來的值一樣; username = request.POST.get("username") password = request.POST.get("password") # 2.進行校驗 # 3.返回應答 if username == "yifchan" and password == "yifchan": return JsonResponse({"res": 1}) else: return JsonResponse({"res": 0})
設計 login_ajax_check 路由:
url(r'^login_ajax_check/$', views.login_ajax_check),
註意:ajax的請求在後臺,不要返回頁面或重定向,無效;比如當前端發登錄的ajax給後端,後端校驗用戶名