Django rest framework(5)----解析器

解析器前戏

有时候我们在接受前端传送的值的时候,会存在这样一个奇怪的现象使用request.body可以取到值,而使用request.POST的时候去不到值,基于这样的情况,究竟是如何造成的呢?

追了以下源码发现  把request.body  中的值转换成 POST 需要满足以下的两个条件,也就是说必须满足以下两个条件,才可以使用request.POST接受值,否则只能使用request.body

1. 请求头要求:
     Content-Type: application/x-www-form-urlencoded
     PS: 如果请求头中的 Content-Type: application/x-www-form-urlencoded,request.POST中才有值(去request.body中解析数据)。
2. 数据格式要求:
     name=alex&age=18&gender=男

PS 以上的两个条件缺一不可

部分源码如下

一般在那些地方默认可以使用request.POST 接受的呢

表单提交:

a. form表单提交
    <form method...>
        input...

    </form>

  

ajax 提交的数据。headers content-type使用默认类型的

$.ajax({
    url:...
    type:POST,
    data:{name:alex,age=18} # 内部转化 name=alex&age=18&gender=男
})

这样的情况是 request.body有值;request.POST无值,如果我们需要取值的话可以这样做   json.loads(request.body)

$.ajax({
    url:...
    type:POST,
    headers:{‘Content-Type‘:"application/json"}
    data:JSON.stringfy({name:alex,age=18}) # {name:alex,age:18...}
})

  

以上的情况判断去使用的时候,我们需要去辨别 headers 中的请求类型,那么有没有一种好的方式,使一切变得简单一些呢,当然下面直接上代码有一个清晰的认识在来追踪它的源码

restframework--解析器使用  

类视图代码如下:

from rest_framework.parsers import JSONParser,FormParser

class ParserView(APIView):
    parser_classes = [JSONParser,FormParser,]
    """
    JSONParser:表示只能解析content-type:application/json头
    JSONParser:表示只能解析content-type:application/x-www-form-urlencoded头
    """

    def post(self,request,*args,**kwargs):
        """
        允许用户发送JSON格式数据
            a. content-type: application/json
            b. {‘name‘:‘alex‘,age:18}
        :param request:
        :param args:
        :param kwargs:
        :return:
        """
        """
        1. 获取用户请求
        2. 获取用户请求体
        3. 根据用户请求头 和 parser_classes = [JSONParser,FormParser,] 中支持的请求头进行比较
        4. JSONParser对象去请求体
        5. request.data
        """
        print(request.data)

        return HttpResponse(‘ParserView‘)

添加url

url(r‘parser/$‘, views.ParserView.as_view()), 

发送 表单的数据

后台打印的数据如下

发送json类型的数据

后台接受打印的数据如下

源码流程

入口  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进行加工,丰富了一些功能
        #Request(
        #     request,
        #     parsers=self.get_parsers(),
        #     authenticators=self.get_authenticators(),
        #     negotiator=self.get_content_negotiator(),
        #     parser_context=parser_context
        # )
        #request(原始request,[BasicAuthentications对象,])
        #获取原生request,request._request
        #获取认证类的对象,request.authticators
        #1.封装request
        request = self.initialize_request(request, *args, **kwargs)
        self.request = request
        self.headers = self.default_response_headers  # deprecate?

        try:
            #2.认证
            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

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(),    #[BasicAuthentication(),],把所有的认证类对象封装到request里面了
            negotiator=self.get_content_negotiator(),
            parser_context=parser_context
        )

get_parsers 获取解析对象的列表

 def get_parsers(self):
        """
        Instantiates and returns the list of parsers that this view can use.
        """
        return [parser() for parser in self.parser_classes]

parser_classes

同样我们可以在settings里面全局配置,我们一般使用的就是全局的配置

REST_FRAMEWORK = {
    #版本
    "DEFAULT_VERSIONING_CLASS":"rest_framework.versioning.URLPathVersioning",
    #解析器
    "DEFAULT_PARSER_CLASSES":["rest_framework.parsers.JSONParser","rest_framework.parsers.FormParser"]
}

原文地址:https://www.cnblogs.com/crazymagic/p/9557733.html

时间: 2024-10-07 11:04:18

Django rest framework(5)----解析器的相关文章

Django Rest Framework之解析器

基本代码结构 urls.py: from django.conf.urls import url, include from web.views.s5_parser import TestView urlpatterns = [ url(r'test/', TestView.as_view(), name='test'), ] views.py: from rest_framework.views import APIView from rest_framework.response impor

Django REST framework之解析器实例以及源码流程分析

解析器 我们都知道源生Django默认只能解析content-type:application/x-www-form-urlencoded头格式的,若果是json格式,form-data格式都要自己处理. 但是在restframework已经为我们做好了,只要配置上,就能帮我们解析请求的数据 举例说明: 表设计: 1 from django.db import models 2 3 4 class UserGroup(models.Model): 5 title = models.CharFie

Django rest framework(5) ---解析器

(1)api/urls.py # api/urls.py from django.urls import path,re_path from .views import UserView,PaserView urlpatterns = [ re_path('(?P<version>[v1|v2]+)/users/', UserView.as_view(),name = 'api_user'), path('paser/', PaserView.as_view(),), #解析 ] (2)vie

django rest framework 之 解析器

一.前言 在前端向后台发送form表单或者ajax数据的时候,django的content_type会拿到请求头中的Content-Type属性然后根据值进行解析. 将request.data中的值放到request.POST中需要满足两个条件 请求头要求: Content-Type: application/x-www-form-urlencoded PS: 如果请求头中的 Content-Type: application/x-www-form-urlencoded,request.POST

rest framework 之解析器

一.示例 1.api/urls.py from django.urls import path, re_path from api.views import UserView, ParserView urlpatterns = [ # path('users/', UserView.as_view()), re_path('(?P<version>[v1|v2]+)/users/', UserView.as_view(), name='api_user'), path('parser/', P

rest framework之解析器

一.内置解析器 REST 框架包括一些内置的Parser类,允许你接受各种媒体类型的请求.还支持定义自己的自定义解析器,解析器用于解析客户端提交的数据. 内置解析器的使用 1.全局设置 可以使用 DEFAULT_PARSER_CLASSES 设置默认的全局解析器.例如,以下设置将只允许带有 JSON 内容的请求,而不是默认的 JSON 或表单数据. REST_FRAMEWORK = { 'DEFAULT_PARSER_CLASSES': ( 'rest_framework.parsers.JSO

Django Rest Framework url注册器组件 | 响应器组件 | 分页器组件

文章参考博主:https://www.cnblogs.com/li-li/p/10103918.html 1.url注册器组件 : 通过DRF的视图组件,数据接口逻辑被我们优化到最后剩下一个类,接下来,我们使用DRF的url控制器来帮助我们自动生成url '''3.使用url注册器组件的url''' #导入模块 from rest_framework import routers router = routers.DefaultRouter() # 3.将需要自动生成url的接口注册到route

轻轻松松学会 DRF Django REST framework

DRF Django REST framework 之 APIView(一) DRF Django REST framework 之 解析器(二) DRF Django REST framework 之 序列化(三) DRF Django REST framework 之 视图组件(四) 持续更新中.... 原文地址:https://www.cnblogs.com/pungchur/p/12028316.html

Django框架深入了解_04(DRF之url控制、解析器、响应器、版本控制、分页)

一.url控制 基本路由写法:最常用 from django.conf.urls import url from django.contrib import admin from app01 import views urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^books/', views.Books.as_view()), url(r'^book/', views.Book.as_view()), url(r'^login/

Django Restful Framework【第四篇】版本、解析器、序列化和请求数据验证

一.版本 程序也来越大时,可能通过版本不同做不同的处理 没用rest_framework之前,我们可以通过以下这样的方式去获取. class UserView(APIView): def get(self,request,*args,**kwargs): version = request.query_params.get('version') print(version) if version=='v1': #如果版本是v1 ret = { 'code':111, 'msg':'版本一的内容'