专栏首页小码农漫漫积累路Django-djangorestframework-请求模块-获取请求参数

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

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Django-中间件-csrf扩展请求伪造拦截中间件-Django Auth模块使用-效仿 django 中间件配置实现功能插拔式效果-09

    django 中间件 就类似于是 django 的门户,请求来的时候需要先经过 中间件 才能到达 django 后端(urls),响应走的时候也需要经过 中间件...

    suwanbin
  • Django-djangorestframework-渲染模块

    入口 dispatch 中的 self.response = self.finalize_response(request, response, *args, ...

    suwanbin
  • Django-多对多关系的三种创建方式-forms组件使用-cookie与session-08

    写法和写模型表类极其相似,但是 forms 组件的字段有约束,模型表类的字段没有约束 from django import forms class...

    suwanbin
  • Spring中获取Request的几种方法及其线程安全性分析

    本文将介绍在Spring MVC开发的Web系统中,获取request对象的几种方法,并讨论其线程安全性。

    Java后端技术
  • Spring 获取 request 的几种方法及其线程安全性分析

    本文将介绍在Spring MVC开发的Web系统中,获取request对象的几种方法,并讨论其线程安全性。

    Java技术栈
  • Spring中获取Request的方法及线程安全性分析

    作者:编程迷思(Java架构沉思录做了部分修改与注释,著作权归原作者所有) 原文:https://www.cnblogs.com/kismetv/p/87572...

    黄泽杰
  • Spring中获取request的几种方法,及其线程安全性分析

    Tanyboye
  • flask中请求勾子

    在客户端和服务器交互的过程中,有些准备工作或扫尾工作需要处理,比如:     *在请求开始时,建立数据库连接;     *在请求开始时,根据需求进行权限校验;...

    py3study
  • python获取代理需要账户和密码代码模板

    小小咸鱼YwY
  • flask 流式响应 RuntimeError: working outside of request context

    1、问题 最近要实现这样一个功能:某个 cgi 处理会很耗时,需要把处理的结果实时的反馈给前端,而不能等到后台全完成了再咔一下全扔前端,那样的用户体验谁都没法接...

    用户1177713

扫码关注云+社区

领取腾讯云代金券