Django restframe view access process source analysis

Access process source code analysis, here we mainly see how the user's request to access our view function.

Note: be sure to follow the blogger's comments to see the code in Chinese and the following code!!!

1. Run project command: Python manage.py Here you can see the entry time of the program manage.py file

#!/usr/bin/env python
"""Django's command-line utility for administrative tasks."""
import os
import sys


def main():
    # Load the global profile of the project
    os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mySwagger.settings')
    try:
        from django.core.management import execute_from_command_line
    except ImportError as exc:
        raise ImportError(
            "Couldn't import Django. Are you sure it's installed and "
            "available on your PYTHONPATH environment variable? Did you "
            "forget to activate a virtual environment?"
        ) from exc
    execute_from_command_line(sys.argv)


if __name__ == '__main__':
    main()
Project's manage.py

2. The program is the global configuration file of the loading project. Here are some global configuration codes,

import os
import sys

# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# To be created APP Place to apps Root directory, easy to manage
sys.path.insert(0,os.path.join(BASE_DIR, 'apps'))

# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/2.2/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = '+6mgo4jn^z8&ydx&@n8q++3x1u3mym+)@yt#fah=qbxyl*wat+'

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

ALLOWED_HOSTS = ['*']


# Application definition

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',

    # built-in APP
    "rest_framework",

    # Self created APP
    "words",
]

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',

    # cors Request Middleware
    'corsheaders.middleware.CorsMiddleware',

    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

ROOT_URLCONF = 'mySwagger.urls'

WSGI_APPLICATION = 'mySwagger.wsgi.application'
mySwagger.settings.py

3. Then run the last line of code, and the application will officially start and wait for the user's request.

4. At this time, the user issues an http request (get, post, put, delete, patch, options, head, trace, etc.), which is executed from top to bottom in the global configuration file

① the app directory (i.e. putting application s one by one) has been created

② application added to install_ In the list of apps (built-in and own)

③ execute the middleware of Django, and add a knowledge point here

Django middleware can only define at most five methods: process_request,  process_view,  process_response,  process_exception,  process_template_response.

What is the relationship between the execution process in Django and the user's request? The user needs to execute all the middleware processes of Django before sending the request_ The request method is as shown in the figure. Finally, according to the route split requested by the user, the main configuration route matching is performed first, then the application route is determined, and then the view function to be executed is matched. However, it is not executed immediately, but all processes of Django middleware are executed_ View method, which is very important. Next, I will introduce process specifically_ One use of view. After the execution, the method of view matching according to the route will be executed. Finally, the other three methods of all Django middleware will be executed according to the return value of the method.

 

 

5. Here I will add the above process_ An important example of the view method: the implementation of the csrftoken Django middleware (Django's own Middleware), whose internal implementation is in the process_ The view method verifies whether the view method based on route matching adds the decorator exempt from verification. There are two kinds of view forms in Django framework: FBV (Function Basic View) and CBV (Class Basic View). Therefore, there are differences between the two kinds of decorators that need to be certified and exempt from certification in actual development.

① in FBV, use the decorator (CSRF_ Exemptexemption, csrf_protect needs authentication) needs to be imported: from django.views.decorators.csrf import csrf_exempt, csrf_protect. We just need to add these two annotations to the method header.

② in CBV, instead of using the above two annotations directly, he needs to import another thing: from django.utils.decorators import method_ decorator. There are two ways to annotate. The first way is to add @ method directly to the class_ Decorator (), the first parameter is one of the above two annotations, and the second parameter name specifies the dispatch method name. The second is to customize a dispatch method in the class and add @ method to the method_ Decorator (comment previous).

And then we finally got back to the point

6. In the fifth part, FBV, CBV and dispatch methods appear. FBV is a function based view, which is directly matched to the view function according to the route, and then the view function gives a return value, which is not better encapsulated and object-oriented, so it is not recommended. CBV is a class based view. It matches the view class according to the route and executes the as of the view class in advance_ View method

from django.conf.urls import url

from . import views


app_name = '[words]'
urlpatterns = [
    url(r'groupsSelectAll/', views.GroupsView.as_view(), name="groupsSelectAll"),   # Phrase information query all

]

7. But there is no as under the GroupsView class_ View method, then go to its parent class APIView to view (click in to see as_view method), here the blogger only copies the method source code, and you only need to see the Chinese comments and the code statements below. In this method, it is worth mentioning the super keyword. If the request view class (that is, GroupsView class, if it inherits multiple parent classes) has another parent class, it will first check whether the parent class has as_view method. In this case, it will execute as in the parent class view of APIView_ View method, and then let's look at the as of the parent class view again_ View method. First as_ The view method is of the APIView class, the second as_ The view method is of the view class.

@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

        # Executing the as_view method
        view = super(APIView, cls).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)

APIView.as_view()
APIView.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))

        # implement view method
        def view(request, *args, **kwargs):
            # there cls This is our request view class. Obviously, this self Is the object of the request attempt class
            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
            # And here's the execution 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

View.as_view()
View.as_view()

8. We are in the second as_ In the view method, you can know that self is the object of our request view class. Through this self, you call the dispatch method. There is no dispatch method in the request view class. Do you want to execute the dispatch method in the APIView class again. Here is the dispatch method mentioned above. There is a line of code handler = getattr(self, request.method.lower(), self.http_method_not_allowed), a small line of code is very quintessence. Here we use the reflection mechanism of python. According to the comments in the blogger's code, this self is the request view class (GroupsView), request.method.lower() is one of the eight user request methods mentioned above. If not, the method with the third parameter will be executed. Therefore, we need to write the right The reflection mechanism of python can reflect and execute the methods defined in the request view class

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
        # Here's the original request Processing, return a new request object
        request = self.initialize_request(request, *args, **kwargs)
        self.request = request
        self.headers = self.default_response_headers  # deprecate?

        try:
            # Initialization (user login authentication, authority authentication, access frequency restriction)
            self.initial(request, *args, **kwargs)

            # Get the appropriate handler method
            if request.method.lower() in self.http_method_names:
                # adopt python The method name of the request view class reflected by the reflection mechanism of
                handler = getattr(self, request.method.lower(),
                                  self.http_method_not_allowed)
            else:
                handler = self.http_method_not_allowed
            
            # Finally, the method to execute the request view class
            response = handler(request, *args, **kwargs)

        except Exception as exc:
            response = self.handle_exception(exc)

        self.response = self.finalize_response(request, response, *args, **kwargs)
        return self.response
APIView.dispatch()

9. Finally, execute the get method of the request view class (assuming the get request sent by the user)

class GroupsView(APIView):

    def get(self, request):
        conditions = {
            "id": request.query_params.get("wid"),
            "name": request.query_params.get("name"),
            "start_time": request.query_params.get("start_time"),
            "end_time": request.query_params.get("end_time"),
        }
        res = DataManager.select_by_conditions("words_groups", None, **conditions)
        return Response(data={"code": 200, "result": res})
GroupsView

Tags: Python Django Attribute Session

Posted on Mon, 01 Jun 2020 05:37:07 -0400 by nymall