日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 综合教程 >内容正文

综合教程

Django 之 CBV

發(fā)布時間:2024/1/4 综合教程 26 生活家
生活随笔 收集整理的這篇文章主要介紹了 Django 之 CBV 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Django 中有兩種編寫方式,FBV 和 CBV,那么什么是 FBV,CBV 又是什么呢?

一、什么是 CBV

FBV(function base views) 就是在視圖里使用函數處理請求(常見)。
CBV(class base views) 就是在視圖里使用類處理請求。

示例:

1、project/urls.py

from django.contrib import admin
from django.urls import path
from app.views import IndexView

urlpatterns = [
    path('admin/', admin.site.urls),
    path('index/', IndexView.as_view()),
]

2、app/views.py

from django.shortcuts import render, HttpResponse
from django.views import View


class IndexView(View):
    def get(self, request, *args, **kwargs):
        print('get')
        return HttpResponse('GET')

    def post(self, request, *args, **kwargs):
        print('post')
        return HttpResponse('POST')

可以看到所有的請求都是在類 IndexView 中處理的,它繼承 View,不管是什么請求,都可以匹配到。

二、源碼分析

1、CBV 在進行路由匹配時,執(zhí)行 as_view() 方法,它是類 View 中的一個方法,源碼 base.py

class View:
    @classonlymethod
    def as_view(cls, **initkwargs):
        """Main entry point for a request-response process."""
        for key in initkwargs:
            if key in cls.http_method_names:
                raise TypeError("You tried to pass in the %s method name as a "
                                "keyword argument to %s(). Don't do that."
                                % (key, cls.__name__))
            if not hasattr(cls, key):
                raise TypeError("%s() received an invalid keyword %r. as_view "
                                "only accepts arguments that are already "
                                "attributes of the class." % (cls.__name__, key))

        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)
        view.view_class = cls
        view.view_initkwargs = initkwargs

        # take name and docstring from class
        update_wrapper(view, cls, updated=())

        # and possible attributes set by decorators
        # like csrf_exempt from dispatch
        update_wrapper(view, cls.dispatch, assigned=())
        return view

2、從上面的源碼中我們可以看到 as_view(),返回 view() 方法。而 view() 又調用執(zhí)行 self.dispatch(request, *args, **kwargs) 方法:

def dispatch(self, request, *args, **kwargs):
	"""
	首先要判斷請求方法是不是在 self.http_method_names 中(即允許的方法列表中)
	通過反射,匹配相應方法 get、post、put、delete 等
	"""
    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)	# 如果匹配上了,就執(zhí)行它,get(requesr, *args, **kwargs)

http_method_names

http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']

3、因此大致的執(zhí)行流程為:

請求過來先執(zhí)行 URL 中的 as_view() 方法
as_view() 返回 view() 方法
view() 方法又調用執(zhí)行 dispatch() 方法
dispatch() 中通過反射的方式來匹配相應的請求,是 get 請求,就執(zhí)行 get() 方法,如果是 post 請求的就執(zhí)行 post() 方法。

三、重寫 dispatch

從上面我們指定 CBV 中,請求過來,執(zhí)行相應視圖函數之前,都會先執(zhí)行 dispatch() 方法。那么如果我們想在處理請求前執(zhí)行某個方法或者就打印點別的東西,我們可以重寫它。

方法一

from django.shortcuts import render, HttpResponse
from django.views import View


class IndexView(View):
    def dispatch(self, request, *args, **kwargs):
        print('before...')
        func = getattr(self, request.method.lower())
        ret = func(self, request, *args, **kwargs)
        print('after...')
        return ret

    def get(self, request, *args, **kwargs):
        print('get')
        return HttpResponse('GET')

    def post(self, request, *args, **kwargs):
        print('post')
        return HttpResponse('POST')

運行結果如下:

before...
get
after...

當有很多個類的時候,不可能每個類都寫一個,可以寫一個基類,其他類繼承基類即可:

class BasePatch(object):
    def dispatch(self, request, *args, **kwargs):
        print('before...')
        func = getattr(self, request.method.lower())
        ret = func(self, request, *args, **kwargs)
        print('after...')
        return ret
    
class IndexView(BasePatch, View):
    pass

這樣 IndexView 就會先去找基類 BaseView 中的 dispatch() 方法,而不是 View 中的。


方法二

也可以繼承父類的 dispatch(),不用自己寫反射邏輯:

class BasePatch(object):
    def dispatch(self, request, *args, **kwargs):
        print('before...')
        ret = super(BasePatch, self).dispatch(request,  *args, **kwargs)
        print('after...')
        return ret

四、CSRF

CBV 中如果想給某個函數免除 csrf_token 認證,可以通過裝飾器的形式實現,但是需要注意的是,裝飾器必須裝飾在類上或者 dispatch 上。

方法一

from django.utils.decorators import method_decorator
from django.views.decorators.csrf import csrf_exempt


class IndexView(View):
    @method_decorator(csrf_exempt)		# 這句
    def dispatch(self, request, *args, **kwargs):
        print('before...')
        func = getattr(self, request.method.lower())
        ret = func(self, request, *args, **kwargs)
        print('after...')
        return ret

方法二

裝飾在類上,不用 dispatch

@method_decorator(csrf_exempt, name='dispatch')
class IndexView(View):
    def get(self, request, *args, **kwargs):
        pass

總結

以上是生活随笔為你收集整理的Django 之 CBV的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。