Django REST framework(二): DRF請求的生命周期

DRF請求生命周期解析

  1. CBV的路由糙申,調(diào)用視圖的as_view(),一般業(yè)務(wù)視圖很少定義自己的as_view()碧注,所有會(huì)找到父類的as_view(),所以請求走的是APIViewas_view()函數(shù)
  2. APIViewas_view調(diào)父類的(django原生)的as_view:view = super().as_view(**initkwargs),還禁用了csrf認(rèn)證,return csrf_exempt(view)
  3. 在父類的as_viewdispatch方法請求走的又是APIViewdispatch
  4. 完成任務(wù)方法交給視圖類的請求函數(shù)處理,得到請求的響應(yīng)結(jié)果烫幕,返回給前臺(tái)

請求步驟拆解

1. 請求進(jìn)來走的是APIViewas_view()函數(shù)

APIViewas_view()函數(shù)主要做了兩件事

  • 調(diào)用父類的as_view,就是Viewas_view()方法
  • 禁用scrftoken認(rèn)證:csrf_exempt(view)
class APIView(View):

    # The following policies may be set at either globally, or per-view.
    renderer_classes = api_settings.DEFAULT_RENDERER_CLASSES
    parser_classes = api_settings.DEFAULT_PARSER_CLASSES
    authentication_classes = api_settings.DEFAULT_AUTHENTICATION_CLASSES
    throttle_classes = api_settings.DEFAULT_THROTTLE_CLASSES
    permission_classes = api_settings.DEFAULT_PERMISSION_CLASSES
    content_negotiation_class = api_settings.DEFAULT_CONTENT_NEGOTIATION_CLASS
    metadata_class = api_settings.DEFAULT_METADATA_CLASS
    versioning_class = api_settings.DEFAULT_VERSIONING_CLASS

    # Allow dependency injection of other settings to make testing easier.
    settings = api_settings

    schema = DefaultSchema()

    @classmethod
    def as_view(cls, **initkwargs):
        """
        Store the original class on the view function.

        This allows us to discover information about the view when we do URL
        reverse lookups.  Used for breadcrumb generation.
        """
        if isinstance(getattr(cls, 'queryset', None), models.query.QuerySet):
            def force_evaluation():
                raise RuntimeError(
                    'Do not evaluate the `.queryset` attribute directly, '
                    'as the result will be cached and reused between requests. '
                    'Use `.all()` or call `.get_queryset()` instead.'
                )
            cls.queryset._fetch_all = force_evaluation

        view = super().as_view(**initkwargs)
        view.cls = cls
        view.initkwargs = initkwargs

        # Note: session based authentication is explicitly CSRF validated,
        # all other authentication is CSRF exempt.
        return csrf_exempt(view)

2. View中的as_view(),調(diào)用self.dispatch()完成請求的分發(fā)

class View:
    """
    Intentionally simple parent class for all views. Only implements
    dispatch-by-method and simple sanity checking.
    """

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

    def __init__(self, **kwargs):
        """
        Constructor. Called in the URLconf; can contain helpful extra
        keyword arguments, and other things.
        """
        # Go through keyword arguments, and either save their values to our
        # instance, or raise an error.
        for key, value in kwargs.items():
            setattr(self, key, value)

    @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):
        # 實(shí)例化產(chǎn)Mylogin的對象妆棒, self = Mylogin(**initkwargs)
            self = cls(**initkwargs)
            if hasattr(self, 'get') and not hasattr(self, 'head'):
                self.head = self.get
            self.setup(request, *args, **kwargs)
            if not hasattr(self, 'request'):
                raise AttributeError(
                    "%s instance has no 'request' attribute. Did you override "
                    "setup() and forget to call super()?" % cls.__name__
                )
                #dispatch返回什么澡腾,瀏覽器就會(huì)收到什么
            return self.dispatch(request, *args, **kwargs)
            # 對象在查找屬性或者方法的時(shí)候,一定要默念糕珊,
            # 先從對象這里找动分,然后從產(chǎn)生對象的類里找,最后從父類里找
        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
        
    def setup(self, request, *args, **kwargs):
        """Initialize attributes shared by all view methods."""
        # 這個(gè)方法僅僅是在給對象新增屬性
        self.request = request
        self.args = args
        self.kwargs = kwargs

3.APIView類中定義了dispatch()方法红选,所有上一步調(diào)用self.dispatch()的時(shí)候會(huì)調(diào)用APIView的dispatch()

APIViewdispatch()做了以下5件事

  • 請求對象的二次封裝:request = self.initialize_request(request, *args, **kwargs)
  • 請求之前發(fā)起三大認(rèn)證澜公,入口函數(shù)是self.initial(request, *args, **kwargs),認(rèn)證不通過,拋出異常
  • 發(fā)出請求:response = handler(request, *args, **kwargs)
  • 請求結(jié)果交給渲染模塊,按照前端要求的渲染類型,返回給前端elf.response = self.finalize_response(request, response, *args, **kwargs)
  • 返回請求結(jié)果
def dispatch(self, request, *args, **kwargs):
        """
        `.dispatch()` is pretty much the same as Django's regular dispatch,
        but with extra hooks for startup, finalize, and exception handling.
        """
        self.args = args
        self.kwargs = kwargs
        # 請求的二次封裝
        request = self.initialize_request(request, *args, **kwargs)
        self.request = request
        self.headers = self.default_response_headers  # deprecate?

        try:
        # 請求之前坟乾,做判斷迹辐,認(rèn)證模塊
            self.initial(request, *args, **kwargs)

            # Get the appropriate handler method
            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

            response = handler(request, *args, **kwargs)
        # 認(rèn)證不通過,拋出異常
        except Exception as exc:
            response = self.handle_exception(exc)
        #finalize_response渲染模塊
        self.response = self.finalize_response(request, response, *args, **kwargs)
        return self.response
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末甚侣,一起剝皮案震驚了整個(gè)濱河市明吩,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌殷费,老刑警劉巖印荔,帶你破解...
    沈念sama閱讀 218,640評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異详羡,居然都是意外死亡仍律,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,254評論 3 395
  • 文/潘曉璐 我一進(jìn)店門实柠,熙熙樓的掌柜王于貴愁眉苦臉地迎上來水泉,“玉大人,你說我怎么就攤上這事主到〔栊校” “怎么了?”我有些...
    開封第一講書人閱讀 165,011評論 0 355
  • 文/不壞的土叔 我叫張陵登钥,是天一觀的道長畔师。 經(jīng)常有香客問我,道長牧牢,這世上最難降的妖魔是什么看锉? 我笑而不...
    開封第一講書人閱讀 58,755評論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮塔鳍,結(jié)果婚禮上伯铣,老公的妹妹穿的比我還像新娘。我一直安慰自己轮纫,他們只是感情好腔寡,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,774評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著掌唾,像睡著了一般放前。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上糯彬,一...
    開封第一講書人閱讀 51,610評論 1 305
  • 那天凭语,我揣著相機(jī)與錄音,去河邊找鬼撩扒。 笑死似扔,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播炒辉,決...
    沈念sama閱讀 40,352評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼豪墅,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了辆脸?” 一聲冷哼從身側(cè)響起但校,我...
    開封第一講書人閱讀 39,257評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎啡氢,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體术裸,經(jīng)...
    沈念sama閱讀 45,717評論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡倘是,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,894評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了袭艺。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片搀崭。...
    茶點(diǎn)故事閱讀 40,021評論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖猾编,靈堂內(nèi)的尸體忽然破棺而出瘤睹,到底是詐尸還是另有隱情,我是刑警寧澤答倡,帶...
    沈念sama閱讀 35,735評論 5 346
  • 正文 年R本政府宣布轰传,位于F島的核電站,受9級特大地震影響瘪撇,放射性物質(zhì)發(fā)生泄漏获茬。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,354評論 3 330
  • 文/蒙蒙 一倔既、第九天 我趴在偏房一處隱蔽的房頂上張望恕曲。 院中可真熱鬧,春花似錦渤涌、人聲如沸佩谣。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,936評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽茸俭。三九已至,卻和暖如春瞳秽,著一層夾襖步出監(jiān)牢的瞬間瓣履,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,054評論 1 270
  • 我被黑心中介騙來泰國打工练俐, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留袖迎,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,224評論 3 371
  • 正文 我出身青樓,卻偏偏與公主長得像燕锥,于是被迫代替她去往敵國和親辜贵。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,974評論 2 355