Django-djangorestframework-請求模塊-獲取請求參數


請求模塊

主要是分析 drf 二次封裝后的 request 對象

以及怎么拿到請求傳遞過來的數據(url 拼接的數據,數據包傳過來的數據)

源碼分析

源碼查看,從 as_view 進到 APIView 類的 dispatch 方法,dispatch 中的 request = self.initialize_request(request, *args, **kwargs) 中入手

rest_framework.views.APIView#dispatch

# ...
	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 = 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

rest_framework.views.APIView#initialize_request

    def initialize_request(self, request, *args, **kwargs):
        """
        Returns the initial request object.
        """
        parser_context = self.get_parser_context(request)

        return Request(
            request,
            parsers=self.get_parsers(),
            authenticators=self.get_authenticators(),
            negotiator=self.get_content_negotiator(),
            parser_context=parser_context
        )

rest_framework.request.Request#__init__

    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__)
        )
		# 二次封裝 request,將原生 request 作為 drf request 對象的 _request 屬性
        self._request = request
        # 雖然 drf 對 request 對象做了二次封裝,但是它也做了完全兼容(見下面的 __getattr__ 方法)
        
        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,)

rest_framework.request.Request#__getattr__ 做了特殊兼容

    def __getattr__(self, attr):
        """
        If an attribute does not exist on this instance, then we also attempt
        to proxy it to the underlying HttpRequest object.
        """
        try:
            # 對原有的 request 做了完全兼容
            return getattr(self._request, attr)
        except AttributeError:
            return self.__getattribute__(attr)

正式使用

--> 所以在 APIView 視圖類的方法中我們可以這樣寫

所以以后

  • url 拼接的參數都可以用 request.query_params 來取
  • 所有請求的數據包方式數據都可以用 request.data 來取,所有數據方式(from-data、json...)它都做解析了
class Test(APIView):
    def get(self, request, *args, **kwargs):
        # 獲取 url 拼接的參數
        print(request._request.GET)  # 二次封裝
        print(request.GET)  # 兼容
        print(request.query_params)  # 擴展,推薦用這個
        
        return Response("drf get ok.")
        
	def post(self, request, *args, **kwargs):
        # 獲取 url 拼接的參數 (所有請求方式都可以攜帶這個)
        print(request._request.GET)
        print(request.GET)  # 兼容
        print(request.query_params)  # 擴展,推薦用這個
        
        # 獲取 post 參數
        print(request._request.POST)  # 拿不到 json 的數據 
        print(request.POST)  # 兼容,拿不到 json 的數據
        print(request.data)  # 擴展,兼容性最強,三種數據方式都可以,推薦用這個
        
        return Response("drf post ok")


總結

  • drf 對原生 request 做了二次封裝,request._request 就是原生 request
  • 原生 request 對象的屬性和方法都可以被 drf 的 request 對象直接訪問(向下兼容)
  • drf 請求的所有 url 拼接參數都被解析到 request.query_params 中,所有數據包數據都被解析到 request.data

任何請求都可以通過 url 拼接參數來傳遞參數,同樣通過 request.query_params 獲取


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM