Django restframework User Access Frequency Control Component Increase and Source Code Analysis

User Access Frequency Control source profiling, similar to user login validation, is necessary to add it again in order to increase memory.

Note: Be sure to follow the blogger's explanation and read the Chinese comment of the code and the line below!!!

1. Prepare a routing and view class, global routing configuration is temporarily ignored, when the process executes to the following url:groupsSelectAll-> as_under GroupsView's view classView() 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

]
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})

2. But there is no as_under the GroupsView classView method, then go to its parent APIView (click in to see as_view method), where the blogger only copies the method source code, you only need to see the Chinese comments and the code statements below.It is worth mentioning the super keyword in this method. If the request view class (that is, the GroupsView class, if it inherits more than one parent) has another parent, it first checks to see if the parent has as_view method.Here it is as_in the parent view that executes APIViewView method, and we'll look at the as_of the parent View againView method.First as_view method is APIView class, 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 parent class 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()
    @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 It's our request view class, and obviously, this self Is the object requesting the 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 then 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()

3. We are in the second as_The view method knows that self is an object of our request view class, through which we call the dispatch method. There is no dispatch method in the request view class, so do we execute the dispatch method in the APIView class again?

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 is native request Processing, returning 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, privilege validation, 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 reflected by the reflection mechanism to the request view class
                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()

4. No other code to look at, let's look directly at the initial method because it has access frequency control capabilities.

def initial(self, request, *args, **kwargs):
        """
        Runs anything that needs to occur prior to calling the method handler.
        """
        self.format_kwarg = self.get_format_suffix(**kwargs)

        # Perform content negotiation and store the accepted info on the request
        neg = self.perform_content_negotiation(request)
        request.accepted_renderer, request.accepted_media_type = neg

        # Determine the API version, if versioning is in use.
        version, scheme = self.determine_version(request, *args, **kwargs)
        request.version, request.versioning_scheme = version, scheme

        # Ensure that the incoming request is permitted
        # User authentication method, this request After processing request
        self.perform_authentication(request)
        # User Rights Verification
        self.check_permissions(request)
        # User Access Frequency Limitation
        self.check_throttles(request)
APIView.initial()

5. This is our user access frequency control code.Blogger adds part of APIView code, check_Code used by the throttles method.We can see what's in the codeSelf.check_Chrottles (request), click in to see check_permissions() method, you can see get_permissions method, which isSelf.permission_Classes variable, that isSelf.permission_Classes = api_Settings.DEFAULT_PERMISSION_CLASSES, which is then similar to User Login Verification in the previous article, is that if there is no such variable name and value in the request view class (the value is a list), REST_in the global configuration file will be used.FRAMEWORK={"DEFAULT_PERMISSION_CLASSES':['Permission validation class full path']}, or we add this variable and value to the request view class

class APIView(View):

    # If this variable and value are not present in the request view class, the global profile value is used
    throttle_classes = api_settings.DEFAULT_THROTTLE_CLASSES

    def check_throttles(self, request):
        """
        Check if request should be throttled.
        Raises an appropriate exception if the request is throttled.
        """
        # Objects of the Loop Access Frequency Control Class
        for throttle in self.get_throttles():
            # Execute method under object allow_request(),If is True Do not process if False´╝îThrow exception information
            if not throttle.allow_request(request, self):
                self.throttled(request, throttle.wait())

    def get_throttles(self):
        """
        Instantiates and returns the list of throttles that this view uses.
        """
        # Returns a list of objects in the Access Frequency Control class
        return [throttle() for throttle in self.throttle_classes]

    def throttled(self, request, wait):
        """
        If request is throttled, determine what kind of exception to raise.
        """
        # Throws an exception to the Access Frequency Control class
        raise exceptions.Throttled(wait)
APIView

6. If not executed in the APIView class abovePermission.has_permission (request, self), we can just point in and see has_permission method.In general, if we customize this user rights validation class, we need to inherit the BasePermission class, so we can override has_directlyThe permission method, which requires that the user currently logged in at the time of validation have permissions for a module.Like this, we can customize a class that only has a charge called VIP or SVIP user access (that's just my idea)

Tags: Python Django Attribute Session

Posted on Tue, 02 Jun 2020 07:00:37 -0400 by Instigate