[Django框架之檢視層]

劉較瘦丫 發表於 2021-05-22
框架 Django

[Django框架之檢視層]

檢視層

Django檢視層, 檢視就是Django專案下的views.py檔案,它的內部是一系列的函式或者是類,用來專門處理客戶端訪問請求後處理請求並且返回相應的資料,相當於一箇中央情報處理系統

小白必會三板斧

  • HttpResponse

    • 返回字串型別的資料
  • render

    • 返回html頁面,還可以使用模板語法
  • redirect

    • 重定向

三板斧本質

django檢視函式必須要返回一個HttpResponse物件? 正確!

django檢視函式必須有一個返回值,並且返回值的資料型別必須是HttpResponse物件

# 研究三者原始碼可以得出結論
# HttpResponse
class HttpResponse(HttpResponseBase):
    """
    An HTTP response class with a string as content.
    # 以字串作為內容的HTTP響應類
    This content that can be read, appended to or replaced.
    # 可以讀取、新增或替換的內容
    """
    streaming = False

    def __init__(self, content=b'', *args, **kwargs):
        super(HttpResponse, self).__init__(*args, **kwargs)
        # 內容是一個位元組串。參見' content '屬性方法
        # Content is a bytestring. See the `content` property methods.
        self.content = content 
        
# render        
def render(request, template_name, context=None, content_type=None, status=None, using=None):
        """
        Returns a HttpResponse whose content is filled with the result of calling
        django.template.loader.render_to_string() with the passed arguments.
        # 返回一個HttpResponse,它的內容中填充了呼叫的結果
		# django.template.loader.render_to_string()和傳遞的引數
        """
        content = loader.render_to_string(template_name, context, request, using=using)
        return HttpResponse(content, content_type, status)
  
# redirect內部是繼承了HttpRespone類

JsonResponse

給前端返回json格式的字串

方式1:自己序列化

import json
def func(request):
    d = {'user':'jason好帥','password':123}    
    res = json.dumps(d,ensure_ascii=False)
    return HttpResponse(res)

方式2: JsonResponse

from django.http import JsonResponse
def func(request):
    d = {'user':'jason好帥','password':123}
    return JsonResponse(d)
 #  return JsonResponse(d,json_dumps_params={'ensure_ascii':False} )
    
ps:額外引數補充
    json_dumps_params={'ensure_ascii':False}  # 看原始碼
    safe=False  # 看報錯資訊
 
# JsonResponse返回的也是HttpResponse物件

上傳檔案

前端form表單上傳檔案注意事項
      1.method必須是post
      2.enctype引數需要修改為multipart/form-data

後端暫時需要注意的是
      1.配置檔案中註釋掉csrfmiddleware中介軟體
      2.通過request.FILES獲取使用者上傳的post檔案資料       
def func3(request):
    if request.method == 'POST':
        print(request.POST)
        file_obj = request.FILES.get('myfile')
        print(file_obj.name)  # 獲取檔名稱
        with open(r'%s'%file_obj.name,'wb') as f:
            for chunks in file_obj.chunks():
                f.write(chunks)
    return render(request,'func3.html')

FBV與CBV

FBV		基於函式的檢視
	FBV使用頻率較低(基礎階段)
	
CBV		基於類的檢視
	CBV實際開發專案使用頻率較高(高階階段)
	
views.py檢視層
	檢視函式
    	不僅僅可以是函式也可以是類
        	1.程式導向式程式設計
            2.物件導向式程式設計

FBV基於函式的檢視(Function base view)我們前面寫的檢視函式都是FBV
CBV基於類的檢視(Class base view)

檢視檔案中除了用一系列的函式來對應處理客戶端請求的資料邏輯外,還可以通過定義類來處理相應的邏輯

CBV基本使用

# views.py
from django.shortcuts import render,HttpResponse,redirect
from django.views import View
class MyView(View):
    def get(self,request):
        return HttpResponse("get方法")
    def post(self,request):
        return HttpResponse("post方法")
    
# urls.py    
url(r'^func4',views.MyView.as_view())
"""為什麼能夠自動根據請求方法的不同執行不同的方法"""

1. CBV與FBV路由匹配本質

# urls.py  
urlpatterns = [
    url(r'^func4',views.MyView.as_view()) # CBV寫法
    # 等價  CBV路由配置本質跟FBV一樣
    url(r'^func4',views.view) # FBV寫法
] 

2. CBV與FBV區別之突破口

知識點:函式名/方法名:加括號執行優先順序最高

CBV寫的是 as_view() 加括號意味著在專案啟動就會執行
那麼我們大膽猜測:
	 要麼是被@staicmethod修飾的靜態方法,就是個普通函式沒有形參
 	 要麼是被@classmethod修飾的類方法,類來調自動將類當做第一個引數傳入

3. 研究一下原始碼

@classonlymethod  # 類方法,就把它看成@classmethod
def as_view(cls, **initkwargs):
    def view(request, *args, **kwargs): # view是as_view的閉包
        self = cls(**initkwargs)  # self = MyView()生成一個我們自己寫的類的物件
        """
        例項化出一個View類的物件,返回一個dispatch()函式,看著跟我們之前寫的
        檢視函式幾乎一毛一樣,那麼我們找一下函式的上級函式沒有這個方法,最後在類
        裡發現了這個dispatch()函式
        """
        return self.dispatch(request, *args, **kwargs)
    return view # 返回一個函式的記憶體地址

def dispatch(self, request, *args, **kwargs):
        # 獲取當前請求並判斷是否屬於正常的請求(8個)
        if request.method.lower() in self.http_method_names:
            # get請求  getattr(物件,'get')   handler = 我們自己寫的get方法
            handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
        else:
            handler = self.http_method_not_allowed
        return handler(request, *args, **kwargs)  # 執行我們寫的get方法並返回該方法的返回值
# 結論:as_view()最終乾的事情就是根據request請求方式來執行檢視類的不同請求方法

總結:以後會經常需要看原始碼,但是在看Python原始碼的時候,一定要時刻提醒自己物件導向屬性方法查詢順序,先從物件自己找,再去產生物件的類裡面去找,之後再去父類找,看原始碼只要看到了self點一個東西,一定要問自己當前這個self到底是誰。