django의view.view 및 DRF의 APIView 소스 분석

29981 단어
하나.classbasedview의 원본 분석
1.django:python 관리자를 시작합니다.py runserver 127.0.0.1:8000 2. settings 2.1 읽기 models를 로드합니다.py   2.2 views.py   2.3 urls.py 2.3.1 실행 시작 asviews(): views.LoginView.as_view (),view 함수 2.3.2를 되돌려줍니다. 이 때 URL은 구체적인 함수에 대응합니다. 2.4 사용자 요청을 기다리기 시작합니다. (127.0.0.1:8000/books/) 2.5에서view 함수를 실행합니다:view (request)
urls.py
from django.urls import path, include, re_path
from classbasedview import views

urlpatterns = [
    re_path('books/$', views.BookView.as_view()),
]

viws.py
from django.views import View

class View:
    http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']
    @classmethod
    def as_view(cls, **initkwargs):
        def view(request, *args, **kwargs):
             #        ,     self,self cls   ,    cls
             # cls   (    cls  BookView),
             #   ,   self  BookView      
             self = cls(**initkwargs)
             if hasattr(self, 'get') and not hasattr(self, 'head'):
                  self.head = self.get
             #    request       request  
             #  self         :   request
             self.request = request
             self.args = args
             self.kwargs = kwargs
             #     self.dispatch()
             return self.dispatch(request, *args, **kwargs)
                        
        return view
                        
     def dispatch(self, request, *args, **kwargs):
         if request.method.lower() in self.http_method_names:
              #   getattr     ,        ,              
              #     :self.handler
              #   handler()
              handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
          else:
             handler = self.http_method_not_allowed
          return handler(request, *args, **kwargs)

class BookView(View):
    def get(self, request):
        pass
                    
    def post(self, request):
        pass

둘.DRF의 APIView 요청 프로세스 및 소스 분석
본질적으로 DRF는 django의 app(startproject)입니다.
  flask:flask-REST
여러 가지 기능이 패키지되어 있습니다.
- APIView(모든 기능은 APIView 기반)
- 파서 어셈블리 - 시리얼화된 어셈블리 - 인증 어셈블리 - 권한 어셈블리 - 뷰 어셈블리
1. 사용법
1.     
    views.py

    from rest_framework.views import APIView
                    
2.   APIView
      class BookView(APIView):
           def get(self, request):
                pass
                            
          def post(self, request):
                pass
                    
3. urls.py
      from django.urls import path, include, re_path
      from classbasedview import views

      urlpatterns = [
            re_path('login/$', views.LoginView.as_view()),
      ]

2. 원본 코드 해석
  1. django:Python 관리자를 시작합니다.py runserver 127.0.0.1:8000   2. settings: 2.1 모델 불러오기.py 2.2 불러오기views.py 2.3 urls를 로드합니다.py       2.3.1 re_path('BookView/$', views.BookView.as view(), as 실행 시작view () 방법 2.3.2 urls.py 불러오기 완료, URL과 보기 함수 간의 귀속 관계가 설정되었습니다.사용자 요청 대기 4.사용자 요청 수신: 127.0.0.0:8000/books/5.url과 보기 함수 간의 귀속 관계를 찾기 시작하고 사용자가 요청한 url에 따라 대응하는 보기 함수를 찾습니다 6.보기 함수view 실행을 시작합니다.self를 실행하기 시작합니다.dispatch()     8. view 함수의 반환 결과를 클라이언트 브라우저에 되돌려줍니다
class View:
    http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']

    def __init__(self, **kwargs):

         for key, value in kwargs.items():
             setattr(self, key, value)

     @classonlymethod
     def as_view(cls, **initkwargs):
         def view(request, *args, **kwargs):
              #        ,BookView     
              self = cls(**initkwargs)
              # self  BookView      
              #     request       self.request
              self.request = request
              self.args = args
              self.kwargs = kwargs
              # view         self.dispatch()
              return self.dispatch(request, *args, **kwargs)
         #    cls BookView
         view.view_class = cls
         view.view_initkwargs = initkwargs

         return view

     class APIView(View):
          @classmethod
          def as_view(cls, **initkwargs):
               # cls BookView

               view = super(APIView, cls).as_view(**initkwargs) # View:view
               view.cls = cls
               view.initkwargs = initkwargs

               #     view  
               return csrf_exempt(view)
                    
           def dispatch(self, request, *args, **kwargs):
               try:
                            
                  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:
                    response = self.handle_exception(exc)

                return self.response

        class BookView(APIView):
             def get(self, request):
                 pass
                        
             def post(self, request):
                 pass

셋.DRF 파서의 요청 프로세스 및 소스 분석
1. 사용법
1.     
    views.py

    from rest_framework.views import APIView
                    
2.   APIView
    class BookView(APIView):
         def get(self, request):
              pass
                            
         def post(self, request):
              pass
                    
3. urls.py
     from django.urls import path, include, re_path
     from classbasedview import views

     urlpatterns = [
         re_path('login/$', views.LoginView.as_view()),
     ]
                    
4. def post(self, request):
       origin_data = request.data
       ....
       return HttpResponse({})

2. 원본 코드 해석
  1. django:Python 관리자를 시작합니다.py runserver 127.0.0.1:8000   2. settings: 2.1 모델 불러오기.py 2.2 불러오기views.py 2.3 urls를 로드합니다.py       2.3.1 re_path('BookView/$', views.BookView.as view(), as 실행 시작view () 방법 2.3.2 urls.py 불러오기 완료, URL과 보기 함수 간의 귀속 관계가 설정되었습니다.사용자 요청 대기 4.사용자 요청 수신: 127.0.0.0:8000/books/POST 5.시작post()     5.1 request.데이터 트리거 해석 작업 5.2 반환값 가져오기 6.view 함수의 반환 결과를 클라이언트 브라우저에 되돌려줍니다
class View:
    http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']

    def __init__(self, **kwargs):

         for key, value in kwargs.items():
              setattr(self, key, value)

    @classonlymethod
    def as_view(cls, **initkwargs):
         def view(request, *args, **kwargs):
              #        ,BookView     
              self = cls(**initkwargs)
              # self  BookView      
              #     request       self.request
              self.request = request
              self.args = args
              self.kwargs = kwargs
              # view         self.dispatch()
              return self.dispatch(request, *args, **kwargs)
          #    cls BookView
          view.view_class = cls
          view.view_initkwargs = initkwargs

          return view
                        
     class Request(object):
           def __init__(self, request, parsers=None, authenticators=None,
                   negotiator=None, parser_context=None):
               elf._request = request
                self.parsers = parsers or ()  # self.get_parsers()     
                        
            #       
            @property
            def data(self):
                 if not _hasattr(self, '_full_data'):
                      self._load_data_and_files()
                 return self._full_data
                        
            def _load_data_and_files(self):
                 """
                 Parses the request content into `self.data`.
                 """
                 if not _hasattr(self, '_data'):
                      #     self._parse()
                      self._data, self._files = self._parse()  # parsed_data
                      if self._files:
                           self._full_data = self._data.copy()
                           self._full_data.update(self._files)
                      else:
                           self._full_data = self._data

                      # if a form media type, copy data & files refs to the underlying
                      # http request so that closable objects are handled appropriately.
                      if is_form_media_type(self.content_type):
                          self._request._post = self.POST
                          self._request._files = self.FILES
                                
             def _parse(self):
                  """
                  Parse the request content, returning a two-tuple of (data, files)

                  May raise an `UnsupportedMediaType`, or `ParseError` exception.
                  """
                  media_type = self.content_type

                  parser = self.negotiator.select_parser(self, self.parsers)

                  if not parser:
                      raise exceptions.UnsupportedMediaType(media_type)

                  try:
                       parsed = parser.parse(stream, media_type, self.parser_context)
                  except Exception:
                            # If we get an exception during parsing, fill in empty data and
                            # re-raise.  Ensures we don't simply repeat the error when
                            # attempting to render the browsable renderer response, or when
                            # logging the request or similar.
                            self._data = QueryDict('', encoding=self._request._encoding)
                            self._files = MultiValueDict()
                            self._full_data = self._data
                            raise

                        # Parser classes may return the raw data, or a
                        # DataAndFiles object.  Unpack the result as required.
                        try:
                            return (parsed.data, parsed.files)
                        except AttributeError:
                            empty_files = MultiValueDict()
                            return (parsed, empty_files)
                                

                class APIView(View):
                    from rest_framework.settings import api_settings

                    parser_classes = api_settings.DEFAULT_PARSER_CLASSES
                    
                    @classmethod
                    def as_view(cls, **initkwargs):
                        # cls BookView

                        view = super(APIView, cls).as_view(**initkwargs) # View:view
                        view.cls = cls
                        view.initkwargs = initkwargs

                        #     view  
                        return csrf_exempt(view)
                    
                    def initialize_request(self, request, *args, **kwargs):
                        from rest_framework.request import Request

                        return Request(
                            request,
                            parsers=self.get_parsers(),
                        )
                        
                    def get_parsers(self):
                        # [, 
                        # , 
                        # ]
                        return [parser() for parser in self.parser_classes]
                    
                    def dispatch(self, request, *args, **kwargs):
                        #    request,    request          
                        request = self.initialize_request(request, *args, **kwargs)
                        self.request = request
                        try:
                            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:
                            response = self.handle_exception(exc)

                        return self.response

                class BookView(APIView):
                    def get(self, request):
                        pass
                        
                    def post(self, request):
                        parsed_data = request.data

 
전재 대상:https://www.cnblogs.com/chenxi67/p/10079413.html

좋은 웹페이지 즐겨찾기