DRF life-cycle framework and source code analysis

installation

pip3 install djangorestframework

 

drf request lifecycle

Preparation for the play:

View layer views.py

from django.shortcuts import render
from rest_framework.views import APIView
from rest_framework.response import Response
# Create your views here.

class test(APIView):
    def get(self,reqeust,*args,**kwargs):
        return Response('drf get ok')
    def post(self,request,*args,**kwargs):
        return Response('drf post ok')

Routing layer urls.py

from django.conf.urls import url,include
from django.contrib import admin

from . import views

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^test/', views.test.as_view()),
]

 

views.test.as_view () to find the start object as_view () method 1. Here, there is no longer looking from the custom test class, yet it is necessary to find a parent class in APIView

Eventually found below, rest_framework \ views.py:

lass 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)   #调用父类的as_view  也就是django原生的base.py中的as_view
        view.cls = cls
        view.initkwargs = initkwargs

        #Note: the session based authentication IS Explicitly CSRF the Validated, 
        # All OTHER IS CSRF authentication exempt. 

        # Inherited APIView view class certification disabled csrf 
        return csrf_exempt (View)

 

2.view = super (). As_view (** initkwargs) method was called the parent class is django as_view method of native base.py

 This again after adds a return csrf_exempt (view) This is the view class inherited APIView disabled csrf certification basis so that you do not need to comment out the settings

3. Called when the second step as_view parent class () method, this method has a key distribution method return self.dispatch (request, * args, ** kwargs)

The following is a method of native django base.py as_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
             # The above are just a few words to the new object properties 
            return self.dispatch (Request, * args, ** kwargs) # Key Distribution get return handler (request, * args, ** kwargs) 
            # actually is the result of the request to execute our own class inside the method to get back to the front desk 
        view.view_class = CLS 
        view.view_initkwargs = initkwargs 

        # the Take name and docstring from class 
        update_wrapper (View, CLS, Updated = ()) 

        # and the SET by the Attributes Decorators Possible 
        # like csrf_exempt from dispatch 
        update_wrapper (View, cls.dispatch, Assigned = ())
         return view

 

4.APIView override the dispatch method  

 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进行加工(添加数据)  请求模块
        request = self.initialize_request(request, *args, **kwargs)
        self.request = request
        self.headers = self.default_response_headers  # deprecate?

        try:
            #Step two: processing copyright permission requests user authentication to restrict access frequency of three authentication module 
            self.initial (Request, * args, ** kwargs) 

            # the Get Handler at The Appropriate Method, 
            IF request.method.lower () in Self. http_method_names: 
                Handler = getattr (Self, request.method.lower (), 
                                  self.http_method_not_allowed) 
            the else : 
                Handler = self.http_method_not_allowed
             # third step: execution: get / post / put / delete function 
            response = handler (request, * args , ** kwargs) 

        the except Exception AS EXC:
             #Here is thrown for errors appear abnormal module is the second step 
            the Response = self.handle_exception (EXC) 

        # Step four: to return the results of the re-processing, rendering module 
        self.response = self.finalize_response (request, response, * args, ** kwargs)
         return self.response

 

5. The method of task processing request function to the view class structure in response to the request to obtain the return to the front

 

Requesting module: request Object

Source entrance

Method APIView dispatch class: request = self.initialize_request (request, * args, ** kwargs)

Source code analysis

"" " 
# Secondary package obtained def request object 
request = self.initialize_request (request, * args , ** kwargs) point into the 

# in the example of the method rest_framework.request.Request 
self._request = request original request as a new born request of the property _request 

# rest_framework.request.Request in __getattr__ method in 
the try: 
    return getattr (self._request, attr) # access the property is fully compatible with the native request 
the except AttributeError: 
    return getAttribute Self .__ __ (attr) 
"" "

 

Key summary

# . 1) drf of original request made two packages, request._request is native request 
# 2) properties and methods native to the request object can be accessed directly (compatible drf request object) 
# . 3) drf request all url splicing parameters are parsed into query_params, all data packets are parsed into data in
the Test LASS (APIView):
     DEF GET (Self, Request, * args, ** kwargs):
         # URL splicing parameters 
        Print (request._request.GET)   # secondary packages 
        Print ( `` request.GET``) # compatible 
        Print (Request .query_params) # expand 

        return the Response ( ' DRF GET OK ' ) 

    DEF POST (Self, request, * args, ** kwargs):
         # all packets carrying the requests embodiment 
        Print (request._request.POST)   # secondary packages 
        Print (request.POST)   # compatible 
        Print (request.data)  # Expand, the strongest compatibility, are three data mode 

        Print (request.query_params) 

        return the Response ( ' DRF POST OK ' )

 

 

Rendering module: Postman browser and request the results of rendering data in a different way

Source entrance

APIView类的dispatch方法中:self.response = self.finalize_response(request, response, *args, **kwargs)

Source code analysis

"" " 
# Finally resolved reponse object data 
self.response = self.finalize_response (request, response, * args, ** kwargs) point into the 

# parse class to get running objects are 
neg = self.perform_content_negotiation (request, force = true) point into 

# parsing class object obtained 
renderers = self.get_renderers () point into 

# renderer_classes request class obtained from the view class, how to instantiate an object class object list parameter parsing 
return [renderer () for renderer in self. renderer_classes] 


# key: Get renderer_classes self.renderer_classes order of 
# class attributes their view class (partial configuration) => 
class attribute type = # APIView> 
# own profile DEFAULT_RENDERER_CLASSES (global) => 
# profile DRF the DEFAULT_RENDERER_CLASSES 
"" "

 

Global Configuration: All view class centrally, in settings.py project

REST_FRAMEWORK = {
    # drf提供的渲染类
    'DEFAULT_RENDERER_CLASSES': [
        'rest_framework.renderers.JSONRenderer',
        'rest_framework.renderers.BrowsableAPIRenderer',
    ],
}

 

Local configuration: one or a number of separate processing entity class, class attributes provide a corresponding class in view views.py

class the Test (APIView):
     DEF GET (Self, Request, * args, ** kwargs):
         return the Response ( ' DRF GET OK ' ) 

    DEF POST (Self, Request, * args, ** kwargs):
         return the Response ( ' DRF OK POST ' ) 

# arranged in setting.py REST_FRAMEWORK, the global configuration is complete, all interfaces unitary 
# if only a specialized part of the interface can be done - partially disposed 
from rest_framework.renderers Import JSONRenderer
 class Test2 (APIView):
     # local Configuring 
    renderer_classes = [JSONRenderer]
     DEF get(self, request, *args, **kwargs):
        return Response('drf get ok 2')

    def post(self, request, *args, **kwargs):
        return Response('drf post ok 2')

 

Guess you like

Origin www.cnblogs.com/s686zhou/p/11680787.html