您好,登錄后才能下訂單哦!
一 Django的視圖函數view
一個視圖函數(類),簡稱視圖,是一個簡單的Python 函數(類),它接受Web請求并且返回Web響應。
響應可以是一張網頁的HTML內容,一個重定向,一個404錯誤,一個XML文檔,或者一張圖片。
無論視圖本身包含什么邏輯,都要返回響應。代碼寫在哪里也無所謂,只要它在你當前項目目錄下面。除此之外沒有更多的要求了——可以說“沒有什么神奇的地方”。為了將代碼放在某處,大家約定成俗將視圖放置在項目(project)或應用程序(app)目錄中的名為views.py
的文件中。
一個簡單的視圖
下面是一個以HTML文檔的形式返回當前日期和時間的視圖:
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
模塊導入了HttpResponse
類,以及Python的datetime
庫。
接著,我們定義了current_datetime
函數。它就是視圖函數。每個視圖函數都使用HttpRequest
對象作為第一個參數,并且通常稱之為request
。
注意,視圖函數的名稱并不重要;不需要用一個統一的命名方式來命名,以便讓Django識別它。我們將其命名為current_datetime
,是因為這個名稱能夠比較準確地反映出它實現的功能。
這個視圖會返回一個HttpResponse
對象,其中包含生成的響應。每個視圖函數都負責返回一個HttpResponse
對象。
Django使用請求和響應對象來通過系統傳遞狀態。
當瀏覽器向服務端請求一個頁面時,Django創建一個HttpRequest對象,該對象包含關于請求的元數據。然后,Django加載相應的視圖,將這個HttpRequest對象作為第一個參數傳遞給視圖函數。
每個視圖負責返回一個HttpResponse對象。視圖層,熟練掌握兩個對象即可:請求對象(request)和響應對象(HttpResponse)
二 CBV和FBV
FBV(function base views) 就是在視圖里使用函數處理請求。
之前都是FBV模式寫的代碼,所以就不寫例子了。
CBV(class base views) 就是在視圖里使用類處理請求。
Python是一個面向對象的編程語言,如果只用函數來開發,有很多面向對象的優點就錯失了(繼承、封裝、多態)。所以Django在后來加入了Class-Based-View。可以讓我們用類寫View。這樣做的優點主要下面兩種:
如果我們要寫一個處理GET方法的view,用函數寫的話是下面這樣。
def login(request): if request.method == 'GET': return render(request, 'login.html')
如果用class-based view寫的話,就是下面這樣:
#類寫法: class LoginView(View): def get(self,request): print('get方法執行了') return render(request,'login2.html') def post(self,request): username=request.POST.get('username') password=request.POST.get('password') print('post方法執行了') print(username,password) return HttpResponse('cg')
Django的url是將一個請求分配給可調用的函數的,而不是一個class。針對這個問題,class-based view提供了一個as_view()
靜態方法(也就是類方法),調用這個方法,會創建一個類的實例,然后通過實例調用dispatch()
方法,dispatch()
方法會根據request的method的不同調用相應的方法來處理request(如get()
,post()
等)。到這里,這些方法和function-based view差不多了,要接收request,得到一個response返回。如果方法沒有定義,會拋出HttpResponseNotAllowed異常。
注意:使用CBV時,urls.py中也做對應的修改::
from django.conf.urls import url,include from django.contrib import admin from app01 import views urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^login2/$', LoginView.as_view()), ]
CBV傳參,和FBV類似,有名分組,無名分組
url寫法:無名分組的
url(r'^cv/(\d{2})/', views.Myd.as_view(),name='cv'), url(r'^cv/(?P<n>\d{2})/', views.Myd.as_view(name='xxx'),name='cv'),#如果想給類的name屬性賦值,前提你的Myd類里面必須有name屬性(類屬性,定義init方法來接受屬性行不通,但是可以自行研究一下,看看如何行通,意義不大),并且之前類里面的name屬性的值會被覆蓋掉
三 使用Mixin(了解)
我覺得要理解django的class-based-view(以下簡稱cbv),首先要明白django引入cbv的目的是什么。在django1.3之前,generic view也就是所謂的通用視圖,使用的是function-based-view(fbv),亦即基于函數的視圖。有人認為fbv比cbv更pythonic,竊以為不然。python的一大重要的特性就是面向對象。而cbv更能體現python的面向對象。cbv是通過class的方式來實現視圖方法的。class相對于function,更能利用多態的特定,因此更容易從宏觀層面上將項目內的比較通用的功能抽象出來。關于多態,不多解釋,有興趣的同學自己Google。總之可以理解為一個東西具有多種形態(的特性)。cbv的實現原理通過看django的源碼就很容易明白,大體就是由url路由到這個cbv之后,通過cbv內部的dispatch方法進行分發,將get請求分發給cbv.get方法處理,將post請求分發給cbv.post方法處理,其他方法類似。怎么利用多態呢?cbv里引入了mixin的概念。Mixin就是寫好了的一些基礎類,然后通過不同的Mixin組合成為最終想要的類。
所以,理解cbv的基礎是,理解Mixin。Django中使用Mixin來重用代碼,一個View Class可以繼承多個Mixin,但是只能繼承一個View(包括View的子類),推薦把View寫在最右邊,多個Mixin寫在左邊。
四 給視圖加裝飾器使用裝飾器裝飾FBV
FBV本身就是一個函數,所以和給普通的函數加裝飾器無差:
from django.shortcuts import render, HttpResponse, redirect def wrapper(f): def innser(*args, **kwargs): print('執行前') ret = f(*args, **kwargs) print('執行后') return ret return innser @wrapper def index(request): print('12321') return render(request, 'index.html')
使用裝飾器裝飾CBV
類中的方法與獨立函數不完全相同,因此不能直接將函數裝飾器應用于類中的方法 ,我們需要先將其轉換為方法裝飾器。
Django中提供了method_decorator裝飾器用于將函數裝飾器轉換為方法裝飾器。
def wrapper(f): def innser(*args, **kwargs): print('執行前') ret = f(*args, **kwargs) print('執行后') return ret return innser from django.views import View from django.utils.decorators import method_decorator @method_decorator(wrapper,name='get') class LoginView(View): # 使用CBV時要注意,請求過來后會先執行dispatch()這個方法,如果需要批量對具體的請求處理方法,如get,post等做一些操作的時候,這里我們可以手動改寫dispatch方法,這個dispatch方法就和在FBV上加裝飾器的效果一樣。 # @method_decorator(wrapper) def dispatch(self, request, *args, **kwargs): # print('之前') ret=super().dispatch(request, *args, **kwargs) # print('之后') return ret # @method_decorator(wrapper) def get(self,request): print('get方法執行了') return render(request,'login2.html') # @method_decorator(wrapper) def post(self,request): username=request.POST.get('username') password=request.POST.get('password') print('post方法執行了') print(username,password) return HttpResponse('cg')
另外給cbv添加裝飾器的時候(先作為了解):
直接添加在dispatch里面,這樣每個函數都會執行
from django.utils.decorators import method_decorator @method_decorator(login_test) def dispatch(self, request, *args, **kwargs): res = super(IndexView, self).dispatch(request, *args, **kwargs) return res
添加在每一個函數中
from django.utils.decorators import method_decorator @method_decorator(login_test) def get(self, request, *args, **kwargs): return render(request, 'index.html')
直接添加在類上,后面的name表示只給get添加裝飾器
from django.utils.decorators import method_decorator @method_decorator(login_test, name='get')
get是給get方法加 (以這種方式如果想給多個方法加裝飾器,需要寫多層裝飾器,因為name這個參數的值必須是個字符串,并且不能同時寫兩個方法)
@method_decorator(login_test, name='post') post是給post方法加 class IndexView(View): def get(self,request): pass
添加裝飾器前必須導入from django.utils.decorators import method_decorator
添加裝飾器的格式必須為@method_decorator(),括號里面為裝飾器的函數名
給類添加是必須聲明name
注意csrf-token裝飾器的特殊性,在CBV模式下它只能加在dispatch上面(后面再說)
下面這是csrf_token的裝飾器:
@csrf_protect,為當前函數強制設置防跨站請求偽造功能,即便settings中沒有設置csrfToken全局中間件。
@csrf_exempt,取消當前函數防跨站請求偽造功能,即便settings中設置了全局中間件。
注意:from django.views.decorators.csrf import csrf_exempt,csrf_protect
五 request對象官方文檔
請求相關的屬性方法(request--HttpRequest對象)
def index(request): #http相關請求信息---封裝--HttpRequest對象 if request.method == 'GET': print(request.body) #獲取post請求提交過來的原始數據 print(request.GET) #獲取GET請求提交的數據 # print(request.META) # 請求頭相關信息,就是一個大字典 print(request.path) #/index/ 路徑 print(request.path_info) #/index/ 路徑 print(request.get_full_path()) #/index/?username=dazhuang&password=123 return render(request,'index.html') else: print(request.body) # b'username=dazhuang' print(request.POST) #獲取POST請求提交的數據 return HttpResponse('男賓三位,拿好手牌!')
六 response對象
與由Django自動創建的HttpRequest對象相比,HttpResponse對象是我們的職責范圍了。我們寫的每個視圖都需要實例化,填充和返回一個HttpResponse。
HttpResponse類位于django.http模塊中。
HttpResponse --- 回復字符串的時候來使用 render --- 回復一個html頁面的時候使用 redirect -- 重定向 示例: def login(request): if request.method == 'GET': return render(request,'login.html') else: username = request.POST.get('username') password = request.POST.get('password') if username == 'taibai' and password == 'dsb': # return render(request,'home.html') return redirect('/home/') #重定向 else: return HttpResponse('滾犢子,趕緊去充錢!!!') #首頁 def home(request): return render(request,'home.html') HttpResponse.content:響應內容 HttpResponse.charset:響應內容的編碼 HttpResponse.status_code:響應的狀態碼
redirect() :給瀏覽器了一個30x的狀態碼
參數可以是:
一個模型:將調用模型的get_absolute_url()
函數
2.一個視圖,可以帶有參數:將使用urlresolvers.reverse
來反向解析名稱
3.一個絕對的或相對的URL,將原封不動的作為重定向的位置。
默認返回一個臨時的重定向;傳遞permanent=True
可以返回一個永久的重定向。
示例:
你可以用多種方式使用redirect()
函數。
def login(request): if request.method == 'GET': return render(request, 'login.html') else: username = request.POST.get('username') password = request.POST.get('password') if username == 'anwen@123' and password == '123': return redirect('/app01/home/') ##重定向到/app01/home/路徑,這也是發送了一個請求,別忘了在上面引入這個redirect類,和render、Httpresponse在一個地方引入 else: return HttpResponse('登錄失敗!') def home(request): return render(request, 'home.html')
#app01里的 urls.py from django.conf.urls import url from app01 import views urlpatterns=[ url(r'^$',views.login), url(r'^home/',views.home), ]
上面幾個文件搞好之后,我們重啟Django項目,然后登陸頁面的輸入網址,注意,你輸入的網址端口要和你啟動的django項目的端口一樣。
| 一點擊提交按鈕,你看一下network里面發送了幾個請求:兩個請求,一個是login請求,一個index請求。 |
擴展閱讀:** key兩次請求,關于301和302:
1)301和302的區別。
301和302狀態碼都表示重定向,就是說瀏覽器在拿到服務器返回的這個狀態碼后會自動跳轉到一個新的URL地址,這個地址可以從響應的Location首部中獲取
(用戶看到的效果就是他輸入的地址A瞬間變成了另一個地址B)——這是它們的共同點。
他們的不同在于。301表示舊地址A的資源已經被永久地移除了(這個資源不可訪問了),搜索引擎在抓取新內容的同時也將舊的網址交換為重定向之后的網址;
302表示舊地址A的資源還在(仍然可以訪問),這個重定向只是臨時地從舊地址A跳轉到地址B,搜索引擎會抓取新的內容而保存舊的網址。 SEO302好于301
2)重定向原因:
(1)網站調整(如改變網頁目錄結構);
(2)網頁被移到一個新地址;
(3)網頁擴展名改變(如應用需要把.php改成.Html或.shtml)。
這種情況下,如果不做重定向,則用戶收藏夾或搜索引擎數據庫中舊地址只能讓訪問客戶得到一個404頁面錯誤信息,訪問流量白白喪失;再者某些注冊了多個域名的網站,也需要通過重定向讓訪問這些域名的用戶自動跳轉到主站點等。
臨時重定向(響應狀態碼:302)和永久重定向(響應狀態碼:301)對普通用戶來說是沒什么區別的,它主要面向的是搜索引擎的機器人。
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持億速云。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。