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:
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')