Django Rest framework 接收text/xml,yaml等格式请求
request 请求Accept
请求头accept
accept: image/webp,image/apng,image/*,*/*;q=0.8
accept 表示我当前的请求希望接受什么类型的文件,这是请求首部,当服务器没有客户端想要的资源的媒体类型时,会返回406 Not Acceptable 响应。当然使用了 * / * 表示愿意接受任意类型的资源, q 表示权重,权重在 0-1 之间,默认为 1 。这里前面几个类型都没有标明,则默认都是 1 ( image/webp,image/apng,image/* 权重都为1),表示优先这些类型,最后的 0.8 表示如果都没有,那么任意的类型都行。
返回response
content-type: image/x-icon
所以这里返回image/x-icon类型也是符合请求的。
Django 不显示.svg标图问题
django1.8 默认不支持显示.svg,所以需要做额外设置,在setting.py文件中加入以下代码,即可解决
mimetypes.add_type("image/svg+xml", ".svg", True)
mimetypes.add_type("image/svg+xml", ".svgz", True)
Rest framework 不支持text/xml application/xml类型的请求
rest_framework 框架默认的是以下的设置
'DEFAULT_PARSER_CLASSES': (
'rest_framework.parsers.JSONParser',
'rest_framework.parsers.FormParser',
'rest_framework.parsers.MultiPartParser'
)
默认是json格式,即以下这种格式的请求
Content-Type: application/json
如果请求是 text/xml 获取 application/xml,text/yaml就会出现下面的错误
Unsupported media type "text/xml" in request
或者
不支持请求中的媒体类型 “text/xml
解决方法:
- 安装djangorestframework-xml 或djangorestframework-yaml
XML:
pip install djangorestframework-xml
YAML:
pip install djangorestframework-yaml
-
修改parser
application/xml 类型请求:
from rest_framework_xml.parsers import XMLParser
from rest_framework.views import APIView
class XMLRequestView(APIView):
parser_classes = (XMLParser, )
text/xml类型请求:
from rest_framework_xml.parsers import XMLParser
from rest_framework.views import APIView
# XMLParser 默认media_type='application/xml'
class TextXMLParser(XMLParser):
media_type = 'text/xml'
class XMLRequestView(APIView):
parser_classes = (TextXMLParser, )
application/yaml类型请求:
from rest_framework_yaml.parsers import YAMLParser
from rest_framework.views import APIView
class YAMLRequestView(APIView):
parser_classes = (YAMLParser, )
原理分析
流程图
先贴两张整个函数调用的流程图
代码分析
从接收请求入口开始分析
url(r'^yamltest', YAMLRequestView.as_view()),
从上面的测试url可以看出,重点需要关注as_view,而YAMLRequestView是继承APIView的。而APIView中点代码并没有包含太多信息,所以需要再追踪上一层View类
View 类中的as_views方法
class View(object):
"""
Intentionally simple parent class for all views. Only implements
dispatch-by-method and simple sanity checking.
"""
http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']
def __init__(self, **kwargs):
"""
Constructor. Called in the URLconf; can contain helpful extra
keyword arguments, and other things.
"""
# Go through keyword arguments, and either save their values to our
# instance, or raise an error.
for key, value in six.iteritems(kwargs):
setattr(self, key, value)
@classonlymethod
def as_view(cls, **initkwargs):
"""
Main entry point for a request-response process.