• 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 获取

  • 相关阅读:
    Git使用入门
    Android系统移植和驱动开发
    搭建Android开发环境
    Android源代码的下载和编译
    Andriod深度探索(卷1)HAL与驱动开发 第十章读书心得
    Andriod深度探索(卷1)HAL与驱动开发 第九章读书心得
    Andriod深度探索(卷1)HAL与驱动开发 第八章读书心得
    Android深度探索(卷1)HAL与驱动开发 第七章读书心得
    Android深度探索(卷1)HAL与驱动开发 第六章读书心得
    Android深度探索(卷1)HAL与驱动开发 第五章读书心得
  • 原文地址:https://www.cnblogs.com/suwanbin/p/12018724.html
Copyright © 2020-2023  润新知