Django之深刻了解視圖層

視圖層三板斧

規定視圖函數必須有一個返回值,前端

而且返回值的數據類型必須是 HttpResponse 對象python

HttpResponse

返回瀏覽器一個字符串django

render

結合一個給定的模板和一個給定的上下文字典,並返回一個渲染後的 HttpResponse 對象。json

redirect

默認返回一個臨時的重定向;傳遞permanent=True 能夠返回一個永久的重定向。後端

擴展閱讀:瀏覽器

臨時重定向(響應狀態碼:302)和永久重定向(響應狀態碼:301)對普通用戶來講是沒什麼區別的,它主要面向的是搜索引擎的機器人。app

A頁面臨時重定向到B頁面,那搜索引擎收錄的就是A頁面。函數

A頁面永久重定向到B頁面,那搜索引擎收錄的就是B頁面。post

JsonResponse

前提知識點:先後端數據要交互,一般狀況下采用json的字符串,後端須要寫好響應的url接口並返回json格式的字符串,前端在訪問你這個接口就好了。

先後端json 序列化和反序列化的方法

方法 後端 前端
序列化 json.dumps JSON.stringfy
反序列化 json.loads JSON.parse

django很是友好,幫咱們想到了這個問題,就有現成的對象來自動轉成json的對象---JsonResponse

# 導入JsonResponse 對象
from django.http import JsonResponse
def index(request):
    user_dict = {'username':'qinyj','age':18,'hobby':'獨角獸的好事'}
    # json數據序列化的時候,若是這個字典裏有中文,
    # 那麼序列化的時候就不能序列化中文了,須要加參數ensure_ascii=False
    return HttpResponse(json.dumps(user_dict,ensure_ascii=False))
    
    # 一樣django幫你想到了這點,直接用jsonresponse對象返回就好了,不須要導入json模塊了。
    # 可是一樣也是不支持中文的,須要加參數json_dumps_params={'ensure_ascii':False}
    return JsonResponse(user_dict,json_dumps_params={'ensure_ascii':False})

    L = [1,2,3,4]
    # json默認是序列化字典用的,若是序列化其餘數據類型的話會報錯:
    # In order to allow non-dict objects to be serialized set the safe parameter to False.
    # 提示必需要加safe參數
    return JsonResponse(L,safe=False)

FBV

基於函數版的視圖任務

def index(request):
    user_dict = {'username':'qinyj','age':18,'hobby':'獨角獸的好事'}
    # json數據序列化的時候,若是這個字典裏有中文,
    # 那麼序列化的時候就不能序列化中文了,須要加參數ensure_ascii=False
    return HttpResponse(json.dumps(user_dict,ensure_ascii=False))
    
    # 一樣django幫你想到了這點,直接用jsonresponse對象返回就好了,不須要導入json模塊了。
    # 可是一樣也是不支持中文的,須要加參數json_dumps_params={'ensure_ascii':False}
    return JsonResponse(user_dict,json_dumps_params={'ensure_ascii':False})

    L = [1,2,3,4]
    # json默認是序列化字典用的,若是序列化其餘數據類型的話會報錯:
    # In order to allow non-dict objects to be serialized set the safe parameter to False.
    # 提示必需要加safe參數
    return JsonResponse(L,safe=False)

而後在urls.py 路由匹配中寫匹配規則
url(r'^index/', views.index)

CBV

基於類版的視圖任務

# 導入View,繼承View類
from django.views import View

class MyLogin(View):
    def get(self,request):
        print("我是MyLog裏面的get方法")
        return render(request,'login.html')

    def post(self,request):
        print("我是MyLog裏面的post方法")
        return HttpResponse("post")
    
而後在urls.py 路由匹配中寫匹配規則,CBV書寫方式有所不一樣
url(r'^login/', views.MyLogin.as_view())
# 經過看源碼的執行流程:
# 訪問類的屬性和方法,方法加括號,執行優先級最高
# 項目一啓動 會自動執行as_views方法
# 第一步  會 變形爲 views.view
# url(r'login/',views.view),
# 而後進入view函數 --> self.dispatch(request, *args, **kwargs) --> if request.method.lower() in self.http_method_names:
    #             handler = getattr(self, request.method.lower(), self.http_method_not_allowed) --> return handler(request, *args, **kwargs)

CBV源碼

咱們經過看CBV執行的流程源碼看出來,能夠思考一個問題,

咱們在視圖中定義兩個方法,get、post

爲何可以根據請求方式的不一樣,自動執行不一樣的方法?

django CBV方式執行源碼重要部分:

路由層經過匹配
url(r'^login/', views.MyLogin.as_view())
首先遇到類名加括號,執行優先級最高,經過調用as_view獲得一個返回值view,把它變形,
url(r'login/',views.view)
而後執行view的方法,會到dispatch方法中執行
判斷請求的方式是什麼,在不在事先定義好的方法列表裏面
而後利用反射獲得對請求方式的對象,再次return出去,執行請求方式對象裏的內容.

@classonlymethod
def as_view(cls, **initkwargs):
    """
        Main entry point for a request-response process.
        """
    ...
    def view(request, *args, **kwargs):
        self = cls(**initkwargs)
        if hasattr(self, 'get') and not hasattr(self, 'head'):
            self.head = self.get
            self.request = request
            self.args = args
            self.kwargs = kwargs
            return self.dispatch(request, *args, **kwargs)
        ...
        update_wrapper(view, cls.dispatch, assigned=())
        return view
    
    def dispatch(self, request, *args, **kwargs):
        # 這裏判斷請求的方式是什麼,在不在事先定義好的方法列表裏面
        # http_method_names = ['get',
        # 'post', 
        # 'put', 
        # 'patch', 
        # 'delete', 
        # 'head', 
        # 'options', 
        # 'trace']
        
        if request.method.lower() in self.http_method_names:
            handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
        else:
            handler = self.http_method_not_allowed
        return handler(request, *args, **kwargs)

如何給FBV和CBV加裝飾器

FBV加裝飾器的方式很簡單,和以前咱們加裝飾器沒有區別。

# 定義一個計算執行時間的裝飾器
def outter(func):
    @wraps(func)
    def inner(*args,**kwargs):
        start_time = time.time()
        res = func(*args,**kwargs)
        end_time = time.time()
        print('執行時間:',end_time - start_time)
        return res
    return inner


# 普通函數加裝飾器
@outter
def index(request):
    user_dict = {'username':'qinyj','age':18,'hobby':'獨角獸的好事'}
    # return HttpResponse(json.dumps(user_dict,ensure_ascii=False))
    # json數據序列化的時候,若是這個字典裏有中文,
    # 那麼序列化的時候就不能序列化中文了,須要加參數ensure_ascii=False


    # 一樣django幫你想到了這點,直接用jsonresponse對象返回就好了,不須要導入json模塊了。
    # return JsonResponse(user_dict,json_dumps_params={'ensure_ascii':False})

    L = [1,2,3,4]
    # json默認是序列化字典用的,若是序列化其餘數據類型的話會報錯:
    # In order to allow non-dict objects to be serialized set the safe parameter to False.
    # 提示必需要加safe參數
    return JsonResponse(L,safe=False)

那麼CBV加加裝飾器如何加?

@method_decorator(outter,name='get')

outter:裝飾器名稱

name=:指定哪一個方法使用裝飾器

# 定義一個計算執行時間的裝飾器
def outter(func):
    @wraps(func)
    def inner(*args,**kwargs):
        start_time = time.time()
        res = func(*args,**kwargs)
        end_time = time.time()
        print('執行時間:',end_time - start_time)
        return res
    return inner

# 導入裝飾器的模塊,官方推薦寫法 
from django.utils.decorators import method_decorator
# 第一種方式:能夠指定給那個方法加
# @method_decorator(outter,name='get')
# @method_decorator(outter,name='post')
# @method_decorator(outter,name='dispatch')
class MyLogin(View):
    # 第二種方式:在此重寫父類dispatch方法,作一些操做,給全部的方法都加上裝飾器。
    @method_decorator(outter)
    def dispatch(self, request, *args, **kwargs):
        return super().dispatch(request, *args, **kwargs)
    
    # 第三中方法:能夠單獨在方法名稱上加裝飾器
    # @method_decorator(outter)
    def get(self,request):
        print("我是MyLog裏面的get方法")
        return render(request,'login.html')

    def post(self,request):
        print("我是MyLog裏面的post方法")
        return HttpResponse("post")
    
執行結果:
我是MyLog裏面的get方法
執行時間: 0.01500082015991211

我是MyLog裏面的post方法
執行時間: 0.0
相關文章
相關標籤/搜索