<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      django restframework框架一

      @(python之路)[django restframework框架初識]
      django restframework框架初識

      1.restframework框架

      django-rest-framework框架,基于django的REST框架,是一個強大靈活的構建Web API的工具包。
      環境準備:

      python3.6 
      pip install django==1.11.7
      pip install djangorestframework
      

      2.基于django CBV實現接口

      urls.py

      from django.conf.urls import url
      from django.contrib import admin
      from app01 import views
      urlpatterns = [
          # url(r'^admin/', admin.site.urls),
          url(r'^user/', views.UserView.as_view()),
      ]
      

      views.py

      from django.shortcuts import render,HttpResponse
      from django.views import View
      
      class UserView(View):
          def get(self,request,*args,**kwargs):
              return HttpResponse("get")
          def post(self,request,*args,**kwargs):
              return HttpResponse("post")
      
          def put(self,request,*args,**kwargs):
              return HttpResponse("put")
          def delete(self,request,*args,**kwargs):
              return HttpResponse("delete")
      

      這樣的化我們就可以通過發送不同的請求來,根據不同請求做出 不同響應。

      2.1 源碼刨析

      問題:為什么他會根據不同請求做出響應?
      我們需要查看as_view都做了什么,思路。我們首先先要找到as_view的父類,也就是View.

      from django.views import View
      class UserView(View):
      	pass
      

      分析源碼:

      @classonlymethod
         def as_view(cls, **initkwargs):
      
             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
                 return self.dispatch(request, *args, **kwargs)
             view.view_class = cls
             view.view_initkwargs = initkwargs
      
      
             update_wrapper(view, cls, updated=())
      
      
             update_wrapper(view, cls.dispatch, assigned=())
             return view
      
      

      我們整體來看,這就是一個閉包

      def as_view():
      	def view():
      		pass
      	return view
      

      所以,我們先分析源碼中的view()

      def view(request, *args, **kwargs):
      		  # 這里的self=UserView()
                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
                # self=UserView()
                # self.dispath    這里dispath返回什么用戶就看到什么。
                return self.dispatch(request, *args, **kwargs)
            view.view_class = cls
            view.view_initkwargs = initkwargs
            update_wrapper(view, cls, updated=())
            update_wrapper(view, cls.dispatch, assigned=())
            return view
      

      dispath詳解

       http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']
      
      
      def dispatch(self, request, *args, **kwargs):
      	# 他會看你請求的方法是不是在http_method_names里邊。
      	# 根據在不在里邊去做出相應的相應。
          if request.method.lower() in self.http_method_names:
      	    # self=UserView
      	    # 他會執行get/post/put/delete/方法,
      	    # getattr找到UserView中http_method_names 中對應的方法執行。
              handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
          else:
              handler = self.http_method_not_allowed
          return handler(request, *args, **kwargs)
      
      

      3django restframwork小試牛刀

      urls.py

      from django.conf.urls import url
      from django.contrib import admin
      from app01 import views
      urlpatterns = [
          # url(r'^admin/', admin.site.urls),
          url(r'^user/', views.UserView.as_view()),
      ]
      

      views.py

      from rest_framework.views import APIView
      
      class UserView(APIView):
          def get(self,request,*args,**kwargs):
              return HttpResponse("get")
          def post(self,request,*args,**kwargs):
              return HttpResponse("post")
          def put(self,request,*args,**kwargs):
              return HttpResponse("put")
          def delete(self,request,*args,**kwargs):
              return HttpResponse("delete")
      

      源碼刨析

      這里是繼承了APIview。我們需要從APIview中尋找as_view,查看他是如何工作的。

      def as_view(cls, **initkwargs):
            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(APIView, cls).as_view(**initkwargs)
            view.cls = cls
            view.initkwargs = initkwargs
      
            return csrf_exempt(view)
      

      ?我們首先來看一下view = super(APIView, cls).as_view(**initkwargs)這條語句。補充:super會根據mro表的繼承順序查找方法。
      ?他會查找原來的as_view方法。原來的as_view返回的是原來的內部的view函數。
      ?往下走,我們發現return csrf_exempt(view),這里我們可以認為,他注釋了django的csrf_token。所以,rest framework不用csrf_token認證。其他事沒有做,還是正常走。找到view在找到dispatch。我們發現父類APIview有自己的dispatch。
      dispatch分析

      def dispatch(self, request, *args, **kwargs):
      	 # 這里的request還是還是原來的request
      	 # arg傳遞的參數
           self.args = args
           self.kwargs = kwargs
           # 將request替換,這里的替換是指將request加了一層封裝;下面將詳細說明,
           # 1. 封裝視圖函數
           request = self.initialize_request(request, *args, **kwargs)
           self.request = request
           self.headers = self.default_response_headers  # deprecate?
      
           try:
      	     # 這里是視圖函數觸發之前就做的操作。
      	     # 2. 在視圖函數值前
               self.initial(request, *args, **kwargs)
      		 # 3. 執行視圖函數
               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)
      
           self.response = self.finalize_response(request, response, *args, **kwargs)
           return self.response
      

      ?這里的request包括:

      • _request = 老的request(以后要用的化就需要.出來)
      • authenticators = 認證的對象列表

      注意:這里的self.request是新的request
      response = handler(request, *args, **kwargs)此處做了一個反射,找到視圖函數。
      2.self.initial

      def initial(self, request, *args, **kwargs):
          self.format_kwarg = self.get_format_suffix(**kwargs)
          neg = self.perform_content_negotiation(request)
          request.accepted_renderer, request.accepted_media_type = neg
          # 2.1 處理版本信息
          version, scheme = self.determine_version(request, *args, **kwargs)
          request.version, request.versioning_scheme = version, scheme
          self.perform_authentication(request)
          self.check_permissions(request)
          self.check_throttles(request)
      

      version, scheme = self.determine_version(request, *args, **kwargs)這里邊就是處理版本相關的信息的。

      def determine_version(self, request, *args, **kwargs):
          if self.versioning_class is None:
              return (None, None)
          # 實例化處理版本的對象,obj = URLPathVersioning()
          scheme = self.versioning_class()
          # 返回的結果
      	    # - 方法取得東西obj.determine_version()-->幫助我們拿版本的。
      	    # - 對象本身;obj
          return (scheme.determine_version(request, *args, **kwargs), scheme)
      

      如果我們在View.py中UserView中寫versioning_class = ‘ ’他會優先執行這里的
      版本具體操縱 請看4.1版本

      1.request處理:
      我們可以先看一下,request是怎么處理的。

       def __init__(self, request, parsers=None, authenticators=None,
                    negotiator=None, parser_context=None):
           assert isinstance(request, HttpRequest), (
               'The `request` argument must be an instance of '
               '`django.http.HttpRequest`, not `{}.{}`.'
               .format(request.__class__.__module__, request.__class__.__name__)
           )
      
           self._request = request
           self.parsers = parsers or ()
           self.authenticators = authenticators or ()
           self.negotiator = negotiator or self._default_negotiator()
           self.parser_context = parser_context
           self._data = Empty
           self._files = Empty
           self._full_data = Empty
           self._content_type = Empty
           self._stream = Empty
      
           if self.parser_context is None:
               self.parser_context = {}
           self.parser_context['request'] = self
           self.parser_context['encoding'] = request.encoding or settings.DEFAULT_CHARSET
      
           force_user = getattr(request, '_force_auth_user', None)
           force_token = getattr(request, '_force_auth_token', None)
           if force_user is not None or force_token is not None:
               forced_auth = ForcedAuthentication(force_user, force_token)
               self.authenticators = (forced_auth,)
      

      initialize_request:這里將request做了封裝。詳解一下。

      def initialize_request(self, request, *args, **kwargs):
      
            parser_context = self.get_parser_context(request)
      	  # 這的request包括認證對像,
            return Request(
                request,
                parsers=self.get_parsers(),
                # 我們先看這里
                # 這里的 authenticators就是一個一個列表,里邊放的是我們自己寫的類的
                #一個一個對象。并且把對象封裝到request中了。
                authenticators=self.get_authenticators(),
                negotiator=self.get_content_negotiator(),
                parser_context=parser_context
            )
      

      ?這里的 authenticators就是一個一個列表,里邊放的是我們自己寫的類的一個一個對象。并且把對象封裝到request中了。這就是認證相關的對象。
      get_authenticators:詳解
      ?這是一個列表生成式;

          def get_authenticators(self):
              return [auth() for auth in self.authentication_classes]
      

      我們再看一下,authentication_classes

      authentication_classes = api_settings.DEFAULT_AUTHENTICATION_CLASSES
      

      ?authentication_classe默認取配置文件里讀.如果我們在自己定義的類class UserView:pass中設置,authentication_classes=[ ],那么它的優先級會比他自己定義的要高。

      我們在views.py中看一下request。

      class UserView(APIView):
      
      
          def get(self,request,*args,**kwargs):
              print(request)
              print(request._request)
              print(request.authenticators)
      ############### 打印 #####################
      <rest_framework.request.Request object at 0x06D20BD0>
      <WSGIRequest: GET '/user/'>
      [<rest_framework.authentication.SessionAuthentication object at 0x07255670>, <rest_framework.authentication.BasicAuthentication object at 0x07255690>]
      
      

      ?我們可以發現,reqeust是rest_framework做好封裝的;而request._request是原來的request.request.authenticators是我們傳遞過去的幾類個對象。

      4.rest framework組件

      4.1 版本

      urls.py

      from django.conf.urls import url
      from django.contrib import admin
      from app01 import views
      urlpatterns = [
          # url(r'^admin/', admin.site.urls),
          url(r'^(?P<version>\w+)/user/', views.UserView.as_view()),
      ]
      

      views.py

      from rest_framework.versioning import URLPathVersioning
      
      class UserView(APIView):
          versioning_class = URLPathVersioning
      
          def get(self,request,*args,**kwargs):
              return HttpResponse("get")
          def post(self,request,*args,**kwargs):
              return HttpResponse("post")
          def put(self,request,*args,**kwargs):
              return HttpResponse("put")
          def delete(self,request,*args,**kwargs):
              return HttpResponse("delete")
      

      我們需要在user前邊加上東西
      ?如果是versioning_class = URLPathVersioning我們來看一下他都做了什么

      class URLPathVersioning(BaseVersioning):
      	  invalid_version_message = _('Invalid version in URL path.')
      	
      	  def determine_version(self, request, *args, **kwargs):
      	      version = kwargs.get(self.version_param, self.default_version)
      	      if not self.is_allowed_version(version):
      	          raise exceptions.NotFound(self.invalid_version_message)
      	      return version
      
      

      version_param

      class BaseVersioning(object):
          default_version = api_settings.DEFAULT_VERSION
          allowed_versions = api_settings.ALLOWED_VERSIONS
          version_param = api_settings.VERSION_PARAM
      

      當我們打印的時候他就會打印版本信息

      class UserView(APIView):
          versioning_class = URLPathVersioning
      
          def get(self,request,*args,**kwargs):
              print(request.version)
              return HttpResponse("get")
        ############# 打印 ##############
      v1
      

      方式二
      urls.py

      from django.conf.urls import url
      from django.contrib import admin
      from app01 import views
      urlpatterns = [
      
          url(r'^user/', views.UserView.as_view()),
      ]
      
      

      views.py

      from rest_framework.versioning import URLPathVersioning,QueryParameterVersioning
      
      class UserView(APIView):
      	# 訪問方式http://127.0.0.1:8000/user/?version=v2
          versioning_class = QueryParameterVersioning
          def get(self,request,*args,**kwargs):
              print(request.version)
      		return HttpResponse("get")
      ################# 打印 ########################
      v2
      

      QueryParameterVersioning

      class QueryParameterVersioning(BaseVersioning):
          invalid_version_message = _('Invalid version in query parameter.')
      
          def determine_version(self, request, *args, **kwargs):
              # 版本信息是在query_params中拿到的
              # query_params = self._request.GET
              #def query_params(self):
      	    #  return self._request.GET
              
              version = request.query_params.get(self.version_param, self.default_version)
              if not self.is_allowed_version(version):
                  raise exceptions.NotFound(self.invalid_version_message)
              return version
      
      

      注意推薦用第一種方式:URLPathVersioning

      重點

      &emsp:我們所用的都是rest_framework默認寫好的配置文件我們需要自己定義一下。我們首先找到然后它的配置文件命,我們在重新定義。

      class APIView(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
      

      一步、urls.py

      from django.conf.urls import url
      from django.contrib import admin
      from app01 import views
      urlpatterns = [
          url(r'^(?P<version>\w+)/user/', views.UserView.as_view()),
      ]
      

      所以我們需要在配置settings.py最下邊添加
      二步、settings.py

      INSTALLED_APPS = [
          'django.contrib.admin',
          'django.contrib.auth',
          'django.contrib.contenttypes',
          'django.contrib.sessions',
          'django.contrib.messages',
          'django.contrib.staticfiles',
          'app01.apps.App01Config',
          'rest_framework',
      ]
      
      
      
      REST_FRAMEWORK = {
        "DEFAULT_VERSIONING_CLASS":"rest_framework.versioning.URLPathVersioning",
          "ALLOWED_VERSIONS":["v1","v2"],
          "DEFAULT_VERSION":"v1"
      
      }
      # rest_framework.versioning.URLPathVersioning 是URLPathVersioning 模塊調用的路徑
      # ALLOWED_VERSIONS 限制版本號,只能訪問v1和v2兩個版本號
      # DEFAULT_VERSION 如果沒有取到,默認取v1
      

      ALLOWED_VERSIONS 由來

      
      class URLPathVersioning(BaseVersioning):
          invalid_version_message = _('Invalid version in URL path.')
          def determine_version(self, request, *args, **kwargs):
              version = kwargs.get(self.version_param, self.default_version)
              if not self.is_allowed_version(version):
                  raise exceptions.NotFound(self.invalid_version_message)
              return version
      #####################################################################
      version_param
      class BaseVersioning(object):
          default_version = api_settings.DEFAULT_VERSION
          allowed_versions = api_settings.ALLOWED_VERSIONS
          version_param = api_settings.VERSION_PARAM
      

      ?當然版本也可以放在視圖局部,根據需求設置;版本可以有好多中可以是請求頭,url;子域名中;這里推薦用我們實現的方式之中。

      三步、views.py

      from rest_framework.versioning import URLPathVersioning
      
      class UserView(APIView):
      
          # versioning_class = URLPathVersioning   如果在這里添加,優先級會高于全局
      
          def get(self,request,*args,**kwargs):
              return HttpResponse("get")
          def post(self,request,*args,**kwargs):
              return HttpResponse("post")
          def put(self,request,*args,**kwargs):
              return HttpResponse("put")
          def delete(self,request,*args,**kwargs):
              return HttpResponse("delete")
      

      這里我們需要注意一下;
      在視圖函數執行之前,我們執行的操作為:

      • 版本控制
      • 認證
      • 權限
      • 訪問頻率控制
      posted @ 2018-05-30 17:19  zz小公子  閱讀(835)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 久久涩综合一区二区三区| 亚洲熟妇自偷自拍另亚洲| 亚洲成人精品综合在线| 日本一区不卡高清更新二区| 免费午夜无码片在线观看影院 | 性欧美vr高清极品| 国产午夜免费高清久久影院| 国产超级va在线观看视频| 内射中出无码护士在线| 甘洛县| 日本一区二区三区激情视频 | 亚洲欧洲日产国无高清码图片 | 国产一区二区不卡在线| 麻豆av一区二区天美传媒| 国产亚洲真人做受在线观看| 日韩国产中文字幕精品| 丰满少妇内射一区| 免费国产一级 片内射老| 一本大道久久a久久综合| 风流老熟女一区二区三区| 国产热A欧美热A在线视频| 人人妻人人澡人人爽| 健康| 少妇人妻偷人一区二区| 欧美在线观看www| 五月天免费中文字幕av| 熟女亚洲综合精品伊人久久| 国产成人精品午夜2022| 亚洲一区二区不卡av| 日韩国产精品中文字幕| 亚洲人成电影在线天堂色| 四虎国产精品免费久久| 麻豆精品久久久久久久99蜜桃| julia无码中文字幕一区| 国产无遮挡又黄又爽高潮| 中文字幕国产精品一二区| 免费午夜无码片在线观看影院| 人妻在线无码一区二区三区| 污污网站18禁在线永久免费观看| 中文国产日韩欧美二视频| 天堂久久天堂av色综合|