Django視圖系統(tǒng)
-
Django的View
- 一個視圖函數(shù)(類),簡稱視圖,是一個簡單的Python 函數(shù)(類),它接受Web請求并且返回Web響應(yīng)。
- 響應(yīng)可以是網(wǎng)頁的HTML內(nèi)容,一個重定向,一個404錯誤,一個XML文檔,或者一張圖片。
- 無論視圖本身包含什么邏輯,都要返回響應(yīng)。代碼寫在哪里也無所謂,只要它在你當(dāng)前項(xiàng)目目錄下面。除此之外沒有更多的要求了——可以說“沒有什么神奇的地方”。為了將代碼放在某處,大家約定成俗將視圖放置在項(xiàng)目(project)或應(yīng)用程序(app)目錄中的名為
views.py的文件中。 - 簡而言之,視圖,就是你寫業(yè)務(wù)邏輯的地方。
-
一個簡單的視圖示例
-
下面是一個在
views.py中以HTML文檔形式返回當(dāng)前日期和時間的視圖:from django.http import HttpResponse import datetime def current_datetime(request): now = datetime.datetime.now() html = "<html><body>It is now %s.</body></html>" % now return HttpResponse(html) -
讓我們來逐行解釋下上面的代碼:
首先,我們從
django.http模塊導(dǎo)入了HttpResponse類,以及Python的datetime庫。-
接著,我們定義了
current_datetime函數(shù)。它就是視圖函數(shù)。每個視圖函數(shù)都使用HttpRequest對象作為第一個參數(shù),并且通常稱之為request。注意,視圖函數(shù)的名稱并不重要;不需要用一個統(tǒng)一的命名方式來命名,以便讓Django識別它。我們將其命名為
current_datetime,是因?yàn)檫@個名稱能夠比較準(zhǔn)確地反映出它實(shí)現(xiàn)的功能。 這個視圖會返回一個
HttpResponse對象,其中包含生成的響應(yīng)。每個視圖函數(shù)都負(fù)責(zé)返回一個HttpResponse對象。Django使用請求和響應(yīng)對象來通過系統(tǒng)傳遞狀態(tài)。當(dāng)瀏覽器向服務(wù)端請求一個頁面時,Django創(chuàng)建一個HttpRequest對象,該對象包含關(guān)于請求的元數(shù)據(jù)。然后,Django加載相應(yīng)的視圖,將這個HttpRequest對象作為第一個參數(shù)傳遞給視圖函數(shù)。每個視圖負(fù)責(zé)返回一個HttpResponse對象。
-
-
FBV和CBV
-
FBV:基于函數(shù)寫的view稱為FBV。
def register(request): ''' 這是一個注冊頁面的函數(shù) :param request: :return: ''' if request.method == 'POST': # 用戶提交注冊信息 username = request.POST.get('username', None) # 通過models.UserInfo.objects對象在數(shù)據(jù)庫中創(chuàng)建這條記錄 models.UserInfo.objects.create(name=username) # 數(shù)據(jù)創(chuàng)建成功后直接跳轉(zhuǎn)到user_list頁面 return redirect('/user_list/') # 如果不為POST,則執(zhí)行下面的語句 return render(request, 'register.html') -
CBV:基于類寫的view稱為CBV。
from django.views import View class Registrer(View): # 需要繼承View def get(self, request): return render(request, 'register.html') def post(self, request): username = request.POST.get('username', None) # 通過models.UserInfo.objects對象在數(shù)據(jù)庫中創(chuàng)建這條記錄 models.UserInfo.objects.create(name=username) # 數(shù)據(jù)創(chuàng)建成功后直接跳轉(zhuǎn)到user_list頁面 return redirect('/user_list/')需要注意的是,若使用CBV,urls.py中調(diào)用類的時候必須加上
.as_Views()# urls.py中 from django.contrib import admin from django.urls import path from app import views urlpatterns = [ # ...... path('register/', views.Register.as_View()), # ...... ]
-
-
視圖裝飾器
Django 提供很多裝飾器,它們可以為視圖支持多種 HTTP 特性。查看 裝飾類 來了解如何在基于類的視圖中使用這些裝飾器。
-
允許的 HTTP 方法
在 django.views.decorators.http 中的裝飾器可以用來根據(jù)請求方法來限制對視圖的訪問。如果條件不滿足,這些裝飾器將返回 django.http.HttpResponseNotAllowed 。
-
require_http_methods(request_method_list)裝飾器可以要求視圖只接受特定的請求方法。from django.views.decorators.http import require_http_methods @require_http_methods(["GET", "POST"]) # 注意:請求方法應(yīng)該是大寫。 def my_view(request): # I can assume now that only GET or POST requests make it this far # ... pass require_GET()裝飾器可以要求視圖只接受 GET 方法。require_POST()裝飾器可以要求視圖只接受 POST 方法。require_safe()裝飾器可以要求視圖只接收 GET 和 HEAD 方法。這些方法通常被認(rèn)為是安全的,因?yàn)樗鼈兂藱z索請求的資源外,沒有特別的操作。
注解
Web 服務(wù)器自動刪除對 HEAD 請求的相應(yīng)內(nèi)容,并保持頭部不變,所以你可以像處理視圖里的 GET 請求一樣處理 HEAD 請求。因?yàn)橐恍┸浖蕾?HEAD 請求(比如鏈接檢測器),因此你需要使用 require_safe 而不是 require_GET 。
-
Request對象和Response對象
-
Request對象(HttpRequest的對象)
-
當(dāng)一個頁面被請求時,Django就會創(chuàng)建一個包含本次請求原信息的HttpRequest對象。并且會將這個對象自動傳遞給響應(yīng)的視圖函數(shù),一般視圖函數(shù)約定俗成地使用 request 參數(shù)承接這個對象。在視圖函數(shù)中,接收的request常用的屬性如下:
request.path_info:返回用戶訪問的url,不包括域名、IP、端口和參數(shù)。request.method:所使用的請求方法(GET還是POST),全大寫表示。request.GET:以字典的形式獲取HTTP信息中的GET參數(shù)。request.POST:以字典的形式獲取HTTP信息中的POST參數(shù)。request.body: 請求體,byte類型 request.POST的數(shù)據(jù)就是從body里面提取到的。request.scheme:以字符串形式獲取請求的方式(http或https)。request.body:以byte形式獲取請求報(bào)文的主體。在處理非 HTTP 形式的報(bào)文時非常有用,例如:二進(jìn)制圖片、XML,Json等。request.path:返回用戶訪問的url,不包括域名、IP、端口和參數(shù)。request.COOKIES:一個標(biāo)準(zhǔn)的Python 字典,包含所有的cookie。鍵和值都為字符串。request.FILES:一個類似于字典的對象,包含所有的上傳文件信息。-
request.META:一個標(biāo)準(zhǔn)的Python 字典,包含所有的HTTP 首部。具體的頭部信息取決于客戶端和服務(wù)器。CONTENT_LENGTH:請求的正文的長度(是一個字符串)CONTENT_TYPE:請求的正文的MIME 類型HTTP_ACCEPT:響應(yīng)可接收的Content-TypeHTTP_ACCEPT_ENCODING:響應(yīng)可接收的編碼。HTTP_ACCEPT_LANGUAGE:響應(yīng)可接收的語言。HTTP_HOST:客服端發(fā)送的HTTP Host 頭部。HTTP_REFERER:Referring 頁面。HTTP_USER_AGENT:客戶端的user-agent 字符串。QUERY_STRING:單個字符串形式的查詢字符串(未解析過的形式)。REMOTE_ADDR:客戶端的IP 地址。REMOTE_HOST:客戶端的主機(jī)名。REMOTE_USER:服務(wù)器認(rèn)證后的用戶。REQUEST_METHOD:一個字符串,例如"GET" 或"POST"。SERVER_NAME:服務(wù)器的主機(jī)名。-
SERVER_PORT:服務(wù)器的端口(是一個字符串)。從上面可以看到,除
CONTENT_LENGTH和CONTENT_TYPE之外,請求中的任何 HTTP 首部轉(zhuǎn)換為 META 的鍵時,都會將所有字母大寫并將連接符替換為下劃線最后加上HTTP_前綴。
request.user:一個AUTH_USER_MODEL類型的對象,獲取當(dāng)前登錄的用戶。request.session:一個既可讀又可寫的類似于字典的對象,表示當(dāng)前的會話。只有當(dāng)Django啟用會話的支持時才可用。
-
request中常用的方法:
-
request.get_host():根據(jù)從HTTP_X_FORWARDED_HOST(如果打開USE_X_FORWARDED_HOST,默認(rèn)為False)和HTTP_HOST頭部信息返回請求的原始主機(jī)。如果這兩個頭部沒有提供相應(yīng)的值,則使用SERVER_NAME和SERVER_PORT,在PEP 3333 中有詳細(xì)描述。USE_X_FORWARDED_HOST是一個布爾值,用于指定是否優(yōu)先使用 X-Forwarded-Host 首部,僅在代理設(shè)置了該首部的情況下,才可以被使用。 -
request.get_full_path():不同于request.path_info,雖然不包括域名、IP、端口,但會包含參數(shù)。 -
request.get_signed_cookie(key, default=RAISE_ERROR, salt='', max_age=None):返回簽名過的Cookie 對應(yīng)的值,如果簽名不再合法則返回django.core.signing.BadSignature。 -
request.is_secure():如果請求時是安全的,則返回True;即請求通是過 HTTPS 發(fā)起的。 -
request.is_ajax():如果請求是通過XMLHttpRequest發(fā)起的,則返回True,方法是檢查HTTP_X_REQUESTED_WITH相應(yīng)的首部是否是字符串XMLHttpRequest。大部分現(xiàn)代的 JavaScript 庫都會發(fā)送這個頭部。如果你編寫自己的XMLHttpRequest調(diào)用(在瀏覽器端),你必須手工設(shè)置這個值來讓is_ajax()可以工作。
-
-
-
-
Response對象
- 與由Django自動創(chuàng)建的HttpRequest對象相比,HttpResponse對象是我們的職責(zé)范圍了。我們寫的每個視圖都需要實(shí)例化,填充和返回一個HttpResponse。HttpResponse類位于django.http模塊中。
-
JsonResponse對象
-
JsonResponse是HttpResponse的子類,專門用來生成JSON編碼的響應(yīng)。
from django.http import JsonResponse def get_josn(): data = {'foo': 'bar'} response = JsonResponse(data) # 默認(rèn)只能傳遞字典類型,如果要傳遞非字典類型需要設(shè)置一下safe關(guān)鍵字參數(shù)。response = JsonResponse(data, safe=False) return response
-