Django (47) drf request lifecycle analysis

preface

Pinduoduo coupon https://m.fenfaw.net/

   generally, after we finish serialization, we will start to write views. In drf, we generally use CBV, that is, class View. The most basic way is to use from rest_framework.views import APIView. APIView inherits from View. We will talk about the details of View later. This chapter describes the request lifecycle of drf
 

Pre preparation

Let's write a view class TestView first. The code is as follows:

from rest_framework.views import APIView
from rest_framework.response import Response
class TestView(APIView):
    def get(self, request, *args, **kwargs):
        return Response("drf get ok")
    def post(self, request, *args, **kwargs):
        return Response("drf post ok")

Note: the Response here must be the Response under drf, not the native HttpResponse or JsonResponse of Django, otherwise an error will occur

Then, in URLs Configure routing in py as follows

urlpatterns = [
    path('test/', views.TestView.as_view(), name="Test"),
]

Then we visit http://127.0.0.1:8000/drf/test/ , the following style will appear, indicating that the request is successful

Then we use POST request to access in the interface tool, and the returned results are as follows:

"drf post ok"

The above two access methods have been successful. Next, we analyze the request process and principle
 

Request lifecycle analysis

First, let's see views. Com from the routing configuration TestView. as_view() calls as under the testview class view_ View method, but when we defined this method above, we did not override as_view () method, so as in the parent APIView will be called_ View method, the source code is as follows:

@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.
    """

    # Determine whether queryset is a queryset object
    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

    # Call as of parent class_ View method
    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.
    # csrf authentication disabled
    return csrf_exempt(view)

Through this line of code, view = super() as_view (* * initkwargs), you can know the as of APIView_ The view method also calls the as of the parent class view_ View method, the source code is as follows:

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 there is a get attribute and there is no head attribute, then head is get
        if hasattr(self, 'get') and not hasattr(self, 'head'):
            self.head = self.get

        # Initializes properties shared by all view methods
        self.setup(request, *args, **kwargs)

        # If there is no request attribute, an exception is reported
        if not hasattr(self, 'request'):
            raise AttributeError(
                "%s instance has no 'request' attribute. Did you override "
                "setup() and forget to call super()?" % cls.__name__
            )

        # Return a 'dispatch' method
        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

as_ The view method returns the view and the view returns the dispatch method. The dispatch method is also the dispatch method under APIView. The source code is as follows:

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
    # Initialize the Request and return the Request object
    request = self.initialize_request(request, *args, **kwargs)
    self.request = request
    self.headers = self.default_response_headers  # deprecate?

    try:
        # Run any action that needs to occur before calling the method handler
        self.initial(request, *args, **kwargs)

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

    except Exception as exc:
        # If an exception occurs before calling the method handler, an exception is run
        response = self.handle_exception(exc)
    
    # Returns a response response object
    self.response = self.finalize_response(request, response, *args, **kwargs)
    return self.response

dispatch returns a response response object, obtains the response result of the request, and returns it to the foreground
 

summary

  1. The url request takes the as of APIView_ View function
  2. As in APIView_ View calls the as of the parent class (django native)_ View, csrf authentication is also disabled
  3. As in the parent class_ The dispatch method in view requests the dispatch of APIView
  4. The task completion method is handed over to the view class function for processing, and the response result of the request is obtained and returned to the foreground

Added by benwhitmore on Mon, 31 Jan 2022 10:39:37 +0200