亞寵展、全球寵物產業風向標——亞洲寵物展覽會深度解析
749
2025-03-31
一、django的View(視圖)
一個視圖函數(類),簡稱視圖,是一個簡單的Python 函數(類),它接受Web請求并且返回Web響應。
響應可以是一張網頁的HTML內容,一個重定向,一個404錯誤,一個XML文檔,或者一張圖片。
無論視圖本身包含什么邏輯,都要返回響應。代碼寫在哪里也無所謂,只要它在你當前項目目錄下面。除此之外沒有更多的要求了——可以說“沒有什么神奇的地方”。為了將代碼放在某處,大家約定成俗將視圖放置在項目(project)或應用程序(app)目錄中的名為views.py的文件中。
1、一個簡單的視圖
下面是一個以HTML文檔的形式返回當前日期和時間的視圖:
from?django.http?import?HttpResponse import?datetime def?current_datetime(request): ????now?=?datetime.datetime.now() ????html?=?"
It?is?now?%s."?%?now ????return?HttpResponse(html)讓我們來逐行解釋下上面的代碼:
首先,我們從?django.http模塊導入了HttpResponse類,以及Python的datetime庫。
接著,我們定義了current_datetime函數。它就是視圖函數。每個視圖函數都使用HttpRequest對象作為第一個參數,并且通常稱之為request。
注意,視圖函數的名稱并不重要;不需要用一個統一的命名方式來命名,以便讓Django識別它。我們將其命名為current_datetime,是因為這個名稱能夠比較準確地反映出它實現的功能。
這個視圖會返回一個HttpResponse對象,其中包含生成的響應。每個視圖函數都負責返回一個HttpResponse對象。
Django使用請求和響應對象來通過系統傳遞狀態。
當瀏覽器向服務端請求一個頁面時,Django創建一個HttpRequest對象,該對象包含關于請求的元數據。然后,Django加載相應的視圖,將這個HttpRequest對象作為第一個參數傳遞給視圖函數。
每個視圖負責返回一個HttpResponse對象。
2、CBV和FBV
我們之前寫過的都是基于函數的view,就叫FBV。還可以把view寫成基于類的。
就拿我們之前寫過的添加班級為例:
1)、FBV版:
#?FBV版添加班級 def?add_class(request): ????if?request.method?==?"POST": ????????class_name?=?request.POST.get("class_name") ????????models.Classes.objects.create(name=class_name) ????????return?redirect("/class_list/") ????return?render(request,?"add_class.html")
2)、CBV版:
#?CBV版添加班級 from?django.views?import?View class?AddClass(View): ????def?get(self,?request): ????????return?render(request,?"add_class.html") ????def?post(self,?request): ????????class_name?=?request.POST.get("class_name") ????????models.Classes.objects.create(name=class_name) ????????return?redirect("/class_list/")
注意:
使用CBV時,urls.py中也做對應的修改:
#?urls.py中 url(r'^add_class/$',?views.AddClass.as_view()),
3、給視圖加裝飾器
1)、使用裝飾器裝飾FBV
FBV本身就是一個函數,所以和給普通的函數加裝飾器無差:
def?wrapper(func): ????def?inner(*args,?**kwargs): ????????start_time?=?time.time() ????????ret?=?func(*args,?**kwargs) ????????end_time?=?time.time() ????????print("used:",?end_time-start_time) ????????return?ret ????return?inner #?FBV版添加班級 @wrapper def?add_class(request): ????if?request.method?==?"POST": ????????class_name?=?request.POST.get("class_name") ????????models.Classes.objects.create(name=class_name) ????????return?redirect("/class_list/") ????return?render(request,?"add_class.html")
2)、使用裝飾器裝飾CBV
類中的方法與獨立函數不完全相同,因此不能直接將函數裝飾器應用于類中的方法 ,我們需要先將其轉換為方法裝飾器。
Django中提供了method_decorator裝飾器用于將函數裝飾器轉換為方法裝飾器。
#?CBV版添加班級 from?django.views?import?View from?django.utils.decorators?import?method_decorator class?AddClass(View): ????@method_decorator(wrapper) ????def?get(self,?request): ????????return?render(request,?"add_class.html") ????def?post(self,?request): ????????class_name?=?request.POST.get("class_name") ????????models.Classes.objects.create(name=class_name) ????????return?redirect("/class_list/")
關于CBV的擴展閱讀:
#?使用CBV時要注意,請求過來后會先執行dispatch()這個方法,如果需要批量對具體的請求處理方法,如get,post等做一些操作的時候,這里我們可以手動改寫dispatch方法,這個dispatch方法就和在FBV上加裝飾器的效果一樣。 class?Login(View):??? ????def?dispatch(self,?request,?*args,?**kwargs): ????????print('before') ????????obj?=?super(Login,self).dispatch(request,?*args,?**kwargs) ????????print('after') ????????return?obj ????def?get(self,request): ????????return?render(request,'login.html')? ????def?post(self,request): ????????print(request.POST.get('user')) ????????return?HttpResponse('Login.post')
二、Request對象和Response對象
1、request對象
當一個頁面被請求時,Django就會創建一個包含本次請求原信息的HttpRequest對象。
Django會將這個對象自動傳遞給響應的視圖函數,一般視圖函數約定俗成地使用 request 參數承接這個對象。
官方文檔
1)、請求相關的常用值
path_info???? 返回用戶訪問url,不包括域名
method????????請求中使用的HTTP方法的字符串表示,全大寫表示。
GET??????????????包含所有HTTP ?GET參數的類字典對象
POST???????????包含所有HTTP POST參數的類字典對象
body????????????請求體,byte類型 request.POST的數據就是從body里面提取到的
2)、屬性
所有的屬性應該被認為是只讀的,除非另有說明。
request屬性相關:
屬性: django將請求報文中的請求行、頭部信息、內容主體封裝成?HttpRequest?類中的屬性。 ???除了特殊說明的之外,其他均為只讀的。 0.HttpRequest.scheme ???表示請求方案的字符串(通常為http或https) 1.HttpRequest.body 一個字符串,代表請求報文的主體。在處理非?HTTP?形式的報文時非常有用,例如:二進制圖片、XML,Json等。 但是,如果要處理表單數據的時候,推薦還是使用?HttpRequest.POST?。 另外,我們還可以用?python?的類文件方法去操作它,詳情參考?HttpRequest.read()?。 2.HttpRequest.path 一個字符串,表示請求的路徑組件(不含域名)。 例如:"/music/bands/the_beatles/" 3.HttpRequest.method 一個字符串,表示請求使用的HTTP?方法。必須使用大寫。 例如:"GET"、"POST" 4.HttpRequest.encoding 一個字符串,表示提交的數據的編碼方式(如果為?None?則表示使用?DEFAULT_CHARSET?的設置,默認為?'utf-8')。 ???這個屬性是可寫的,你可以修改它來修改訪問表單數據使用的編碼。 ???接下來對屬性的任何訪問(例如從?GET?或?POST?中讀取數據)將使用新的?encoding?值。 ???如果你知道表單數據的編碼不是?DEFAULT_CHARSET?,則使用它。? 5.HttpRequest.GET? 一個類似于字典的對象,包含?HTTP?GET?的所有參數。詳情請參考?QueryDict?對象。 6.HttpRequest.POST 一個類似于字典的對象,如果請求中包含表單數據,則將這些數據封裝成?QueryDict?對象。 POST?請求可以帶有空的?POST?字典?——?如果通過?HTTP?POST?方法發送一個表單,但是表單中沒有任何的數據,QueryDict?對象依然會被創建。 ???因此,不應該使用?if?request.POST??來檢查使用的是否是POST?方法;應該使用?if?request.method?==?"POST"? 另外:如果使用?POST?上傳文件的話,文件信息將包含在?FILES?屬性中。 ?7.HttpRequest.COOKIES 一個標準的Python?字典,包含所有的cookie。鍵和值都為字符串。 8.HttpRequest.FILES 一個類似于字典的對象,包含所有的上傳文件信息。 ???FILES?中的每個鍵為?中的name,值則為對應的數據。 注意,FILES?只有在請求的方法為POST?且提交的