Django - DRF - 框架介紹、APIview分析

目錄

一、DRF框架 - Django REST Framework

1-1 DRF框架介紹 - 官方文檔

1-2 安裝

二、APIview源碼分析

2-1  as_view方法源碼 - 局部禁用Django自帶的csrf組件

2-2 dispatch - 使用APIview的dispatch進行請求分發處理,對request進行了處理

2-3 initialize_request - 返回新處理的request,既包含了原有屬性又增加了相應屬性

2-4 request - 對request進行處理,getattr和setattr的處理

2-4-1 __getattr__處理對DRF內request內不存在屬性的請求

2-4-2 request.data  - 存儲前臺傳輸原body體內數據

2-4-3 request.query_params - 存儲原始GET內數據

三、使用DRF的簡單數據操作


一、DRF框架 - Django REST Framework

1-1 DRF框架介紹 - 官方文檔

  Django REST框架是用於構建Web api的強大而靈活的工具包,即Django內置模塊的拓展,可視爲Django的第三方APP插件包。

  • Web可瀏覽API對於開發人員來說是一個巨大的可用性勝利。
  • 身份驗證策略,包括OAuth1a和OAuth2的包。
  • 同時支持ORM和非ORM數據源的序列化。
  • 可自定義的——如果不需要更強大的功能,只需使用常規的基於功能的視圖。
  • 豐富的文檔和強大的社區支持。
  • 得到Mozilla、Red Hat、Heroku、Eventbrite等國際知名公司的使用和信任。

1-2 安裝

  • 方式一:pip3 install djangorestframework
  • 方式二:pycharm圖形化界面安裝
  • 方式三:pycharm命令行下安裝(裝在當前工程所用的解釋器下)
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',
]

 

二、APIview源碼分析

2-1  as_view方法源碼 - 局部禁用Django自帶的csrf組件

@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.
    將原始類存儲在視圖函數中。這允許我們在執行URLreverse查找時發現關於視圖的信息。用於生成導航。

    """
    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

    # Note: session based authentication is explicitly CSRF validated,
    # all other authentication is CSRF exempt.
    # 局部禁用Django自帶的csrf組件
    return csrf_exempt(view)

2-2 dispatch - 使用APIview的dispatch進行請求分發處理,對request進行了處理

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.

    ' .dispatch() '與Django的常規調度非常相似,
    但是有額外的鉤子用於啓動、finalize和異常處理。

    """
    self.args = args
    self.kwargs = kwargs
    # request參數爲原始request,以及後續有名分組等傳輸參數
    request = self.initialize_request(request, *args, **kwargs)
    self.request = request
    self.headers = self.default_response_headers  # deprecate?

    try:
        self.initial(request, *args, **kwargs)

        # Get the appropriate handler method
        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

2-3 initialize_request - 返回新處理的request,既包含了原有屬性又增加了相應屬性

def initialize_request(self, request, *args, **kwargs):
    """
    Returns the initial request object.
    返回初始請求對象。
    """
    parser_context = self.get_parser_context(request)
    
    # 類實例化產生了對象,產生新的DRF的request
    return Request(
        request,
        # 用於解析(獲取解析器)
        parsers=self.get_parsers(),
        # 用於認證
        authenticators=self.get_authenticators(),
        # 用於分頁
        negotiator=self.get_content_negotiator(),
        # 用於解析
        parser_context=parser_context
    )

2-4 request - 對request進行處理,getattr和setattr的處理

class Request(object):
    """
    Wrapper allowing to enhance a standard `HttpRequest` instance.

    Kwargs:
        - request(HttpRequest). The original request instance.
        - parsers_classes(list/tuple). The parsers to use for parsing the
          request content.
        - authentication_classes(list/tuple). The authentications used to try
              authenticating the request's user.

   包裝器允許增強一個標準的HttpRequest實例。
   Kwargs:
        -請求(HttpRequest)。原始請求實例。
        - parsers_classes(列表/元組)。用於解析的解析器請求的內容。
        = authentication_classes(列表/元組)。用於嘗試的驗證驗證請求的用戶。
    """

    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,)


   

2-4-1 __getattr__處理對DRF內request內不存在屬性的請求

def __getattr__(self, attr):
"""
位於request類內
實現效果:若外部調用DRF內不存在的屬性,會去_request查找,_request在init內被賦予原始request

If an attribute does not exist on this instance, then we also attempt
to proxy it to the underlying HttpRequest object.
如果這個實例上不存在屬性,那麼我們也會嘗試將其代理到底層HttpRequest對象。
"""
try:
    # getattr獲取self._request內attr屬性的值,若找不到屬性 自動返回None
    return getattr(self._request, attr)
except AttributeError:
    return self.__getattribute__(attr)

2-4-2 request.data  - 存儲前臺傳輸原body體內數據

@property
def data(self):
'''request內方法,被@property隱藏爲屬性使用'''
    if not _hasattr(self, '_full_data'):
        self._load_data_and_files()
    return self._full_data

2-4-3 request.query_params - 存儲原始GET內數據

@property
def query_params(self):
"""
 More semantically correct name for request.GET.
"""
return self._request.GET

三、使用DRF的簡單數據操作

from rest_framework.views import APIView
class Books(APIView):
    # rest_framework.request下的Request作爲參數傳入
    def put(self, request, pk):
        # django.core.handlers.wsgi.WSGIRequest----原來的djagno中的request的類
        # 現在的request已經成了:rest_framework.request.Request
        # print(request.PUT)
        # 以後再取數據,直接從request.data中取
        print(request.data)
        # 前端傳過來的編碼格式:json格式:{'name': '水都是', 'price': '15'}
        # 前端傳過來的編碼格式:urlencoded格式:<QueryDict: {'name': ['紅樓夢'], 'price': ['15']}>

        # request.data是誰的對象?
        # request.data不同編碼格式過來,它可能是不同類的對象,但是用法是一樣的

        # 原來的request是:request._request
        print(type(request._request))
        
        # 由於__getattr__可以直接使用原有方式獲取數據
        # 下列二者相同,也能取出來(method,GET,POST,BODY)
        print(request._request.GET)
        print(request.GET)

        return JsonResponse({'status': 100, 'msg': '修改成功'})

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章