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/', ParserView.as_view(), name='api_parer'),        # 添加这句
]

2、api/views.py

  • JSONParser:只能解析content-type:application/json的头
  • FormParser:只能解析content-type:application/x-www-form-urlencoded的头
from rest_framework.parsers import JSONParser, FormParser

class ParserView(APIView):
    parser_classes = [JSONParser, FormParser]

    def post(self, request, *args, **kwargs):
        print(request.data)

        return HttpResponse('解析')

3、使用 postman 发送 json 数据测试后台是否能解析:

(1)、设置为 post 方式,headers 中添加数据类型为 json

(2)、body 中选择 raw,然后选择 json 类型,最后就是在空白处构建要发送的 json 数据(记得是双引号):

后台结果:

如果是 content-type:application/x-www-form-urlencoded 类型数据,不需要设置请求头,默认就是。但是 body 中需要设置为 x-www-form-urlencoded

二、源码分析

1、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(request,parsers=self.get_parsers(),authenticators=self.get_authenticators(),negotiator=self.get_content_negotiator(),parser_context=parser_context)
    # 第一个参数为原生的 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、initialize_request()

def initialize_request(self, request, *args, **kwargs):
    """
    Returns the initial request object. 封装原生 request 对象
    """
    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
    )

3、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]

4、parser_classes

class APIView(View):

    # The following policies may be set at either globally, or per-view.
    renderer_classes = api_settings.DEFAULT_RENDERER_CLASSES
    # 从 settings 中获取解析器
    parser_classes = api_settings.DEFAULT_PARSER_CLASSES

    # Allow dependency injection of other settings to make testing easier.
    settings = api_settings

5、全局配置解析器 settings

REST_FRAMEWORK = {
    # 解析器
    "DEFAULT_PARSER_CLASSES":["rest_framework.parsers.JSONParser","rest_framework.parsers.FormParser"]
}

源码流程图



根据请求头 content-type 选择对应的解析器就请求体内容进行处理。

三、仅处理请求头 content-type 为 application/json 的请求体

1、urls.py

from django.urls import path, re_path, include
from api.views import TestView2

urlpatterns = [
    re_path(r'(?P<version>[v1|v2]+)/test2', TestView2.as_view()),
]

2、views.py

rom rest_framework.views import APIView
from rest_framework.parsers import JSONParser, FormParser
from rest_framework.response import Response

class TestView2(APIView):
    parser_classes = [JSONParser]

    def post(self, request, *args, **kwargs):
        print(request.content_type)    # application/json

        # 获取请求值,并发 JSONParser  处理
        print(request.data)     # {'name': 'rose', 'age': 18}

        # application/x-www-form-urlencoded 或 multipart/form-data时,request.POST中才有值
        print(request.POST)         # <QueryDict: {}>
        print(request.FILES)        # <MultiValueDict: {}>

        return Response('响应内容')

四、仅处理请求头 content-type 为 application/x-www-form-urlencoded 的请求体

1、urls.py

from django.urls import path, re_path, include
from api.views import TestView2

urlpatterns = [
    re_path(r'(?P<version>[v1|v2]+)/test2', TestView2.as_view()),
]

2、views.py

rom rest_framework.views import APIView
from rest_framework.parsers import JSONParser, FormParser
from rest_framework.response import Response

class TestView2(APIView):
    parser_classes = [FormParser]

    def post(self, request, *args, **kwargs):
        print(request.content_type)    # application/x-www-form-urlencoded

        # 获取请求值,并发 JSONParser  处理
        print(request.data)     # <QueryDict: {'123': ['']}>

        # application/x-www-form-urlencoded 或 multipart/form-data时,request.POST中才有值
        print(request.POST)         # <QueryDict: {'123': ['']}>
        print(request.FILES)        # <MultiValueDict: {}>

        return Response('响应内容')

五、仅处理请求头content-type为multipart/form-data的请求体

1、urls.py

from django.urls import path, re_path, include
from api.views import TestView2

urlpatterns = [
    re_path(r'(?P<version>[v1|v2]+)/test2', TestView2.as_view()),
]

2、views.py

rom rest_framework.views import APIView
from rest_framework.parsers import JSONParser, FormParser, MultiPartParser
from rest_framework.response import Response

class TestView2(APIView):
    parser_classes = [MultiPartParser]

    def post(self, request, *args, **kwargs):
        print(request.content_type)    # multipart/form-data

        # 获取请求值,并发 JSONParser  处理
        print(request.data)    

        # application/x-www-form-urlencoded 或 multipart/form-data时,request.POST中才有值
        print(request.POST)
        print(request.FILES)        

        return Response('响应内容')

3、upload.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="http://127.0.0.1:8000/test/" method="post" enctype="multipart/form-data">
    <input type="text" name="user" />
    <input type="file" name="img">

    <input type="submit" value="提交">

</form>
</body>
</html>

六、仅上传文件

1、urls.py

from django.urls import path, re_path, include
from api.views import TestView2

urlpatterns = [
    re_path(r'(?P<version>[v1|v2]+)/test2', TestView2.as_view()),
]

2、views.py

rom rest_framework.views import APIView
from rest_framework.parsers import JSONParser, FormParser, MultiPartParser, FileUploadParser
from rest_framework.response import Response

class TestView2(APIView):
    parser_classes = [FileUploadParser]

    def post(self, request, *args, **kwargs):
        print(request.content_type)    

        # 获取请求值,并发 JSONParser  处理
        print(request.data)    

        # application/x-www-form-urlencoded 或 multipart/form-data时,request.POST中才有值
        print(request.POST)
        print(request.FILES)        

        return Response('响应内容')

3、upload.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="http://127.0.0.1:8000/test/" method="post" enctype="multipart/form-data">
    <input type="text" name="user" />
    <input type="file" name="img">

    <input type="submit" value="提交">

</form>
</body>
</html>

七、其他

多个 parser

当同时使用多个 parser 时,rest framework 会根据请求头 content-type 自动进行比对,并使用对应 parser

#!/usr/bin/env python
# -*- coding:utf-8 -*-
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.request import Request
from rest_framework.parsers import JSONParser, FormParser, MultiPartParser

class TestView(APIView):
    parser_classes = [JSONParser, FormParser, MultiPartParser, ]

    def post(self, request, *args, **kwargs):
        print(request.content_type)

        # 获取请求的值,并使用对应的JSONParser进行处理
        print(request.data)
        # application/x-www-form-urlencoded 或 multipart/form-data时,request.POST中才有值
        print(request.POST)
        print(request.FILES)
        return Response('POST请求,响应内容')


全局使用

settings.py

REST_FRAMEWORK = {
    'DEFAULT_PARSER_CLASSES':[
        'rest_framework.parsers.JSONParser'
        'rest_framework.parsers.FormParser'
        'rest_framework.parsers.MultiPartParser'
    ]

}

Tips: 个别特殊的值可以通过Django的request对象 request._request 来进行获取

总结

  • JSONParser,解析数据类型:content-type:application/json
  • FormParser,解析数据类型:content-type:application/x-www-form-urlencoded
  • 支持全局配置解析器类型

原文地址:https://www.cnblogs.com/midworld/p/11380172.html

时间: 2024-07-31 08:59:34

rest framework 之解析器的相关文章

rest framework之解析器

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

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

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':'版本一的内容'

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

解析器前戏 有时候我们在接受前端传送的值的时候,会存在这样一个奇怪的现象使用request.body可以取到值,而使用request.POST的时候去不到值,基于这样的情况,究竟是如何造成的呢? 追了以下源码发现  把request.body  中的值转换成 POST 需要满足以下的两个条件,也就是说必须满足以下两个条件,才可以使用request.POST接受值,否则只能使用request.body 1. 请求头要求: Content-Type: application/x-www-form-u

django rest framework 解析器组件 接口设计,视图组件 (1)

一.解析器组件 -解析器组件是用来解析用户请求数据的(application/json), content-type 将客户端发来的json数据进行解析 -必须适应APIView -request.data触发 二.序列化组件 2.1.django 自带组件serializer 2.1.1 from django.serializers import serialize2.1.2 origin_data = Book.objects.all()2.1.3 serialized_data = se

9.6 rest framework 解析器,渲染器

解析器 解析器的作用 解析器的作用就是服务端接收客户端传过来的数据,把数据解析成自己可以处理的数据.本质就是对请求体中的数据进行解析. 请求体相关字段: Accept:指定了接收的数据类型 ContentType:指定了传递的数据类型 解析器工作原理的就是拿到请求的ContentType来判断前端给我的数据类型是什么,然后我们在后端使用相应的解析器去解析数据. ps: django 原生是不支持 json 类型的数据,数据通过request.get 是拿不到的,只能在 request.body