天天看點

[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到底是誰。

繼續閱讀