思考一下:为什么前端的形态不一致,请求drf接口返回的数据形式不一致?
定义
所谓的渲染器(Renderer),其实就是将服务器生成的数据的格式转换为HTTP请求的格式。
REST框架包含许多内置的Renderer类,可以返回各种媒体类型的响应。还支持定义自定义渲染
器,灵活地设计自己的媒体类型。
渲染模块的源码入口:APIView类的dispatch方法中
self.response = self.finalize_response(request, response, *args, **kwargs)
- 查看:
finalize_response(request, response, *args, **kwargs)
def finalize_response(self, request, response, *args, **kwargs):
"""
Returns the final response object.
"""
# Make the error obvious if a proper response is not returned
assert isinstance(response, HttpResponseBase), (
'Expected a `Response`, `HttpResponse` or `HttpStreamingResponse` '
'to be returned from the view, but received a `%s`'
% type(response)
)
if isinstance(response, Response):
if not getattr(request, 'accepted_renderer', None):
neg = self.perform_content_negotiation(request, force=True)
request.accepted_renderer, request.accepted_media_type = neg
response.accepted_renderer = request.accepted_renderer
response.accepted_media_type = request.accepted_media_type
response.renderer_context = self.get_renderer_context()
# Add new vary headers to the response instead of overwriting.
vary_headers = self.headers.pop('Vary', None)
if vary_headers is not None:
patch_vary_headers(response, cc_delim_re.split(vary_headers))
for key, value in self.headers.items():
response[key] = value
return response
- 拿到运行解析类的对象们:
self.perform_content_negotiation(request, force=True)
def perform_content_negotiation(self, request, force=False):
"""
Determine which renderer and media type to use render the response.
"""
renderers = self.get_renderers()
conneg = self.get_content_negotiator()
try:
return conneg.select_renderer(request, renderers, self.format_kwarg)
except Exception:
if force:
return (renderers[0], renderers[0].media_type)
raise
- 获取解析类对象:
renderers = self.get_renderers()
def get_renderers(self):
"""
Instantiates and returns the list of renderers that this view can use.
"""
return [renderer() for renderer in self.renderer_classes]
-
从
self.renderer_classes
获取renderer_classes
,然后从api_settings
中获取渲染模块的配置,获取的顺序如下,所有优先级也是从上至下
1.自己视图类的类属性(局部配置)2.
APIView
类的类属性设置3.自己配置文件的
DEFAULT_RENDERER_CLASSES
(全局配置)4.DRF配置文件的
DEFAULT_RENDERER_CLASSES
自定义配置渲染模块
全局配置
setting.py
文件下加入以下配置:所有视图类统一处理,以下设置也是默认设置
REST_FRAMEWORK = {
# drf提供的渲染类
'DEFAULT_RENDERER_CLASSES': [
'rest_framework.renderers.JSONRenderer', #只显示出json数据
'rest_framework.renderers.BrowsableAPIRenderer', #渲染出页面,注意是BrowsableAPIRenderer
],
}
局部配置
- 某一个或一些实体类单独处理,在
views.py
视图类中提供对应的类属性
from rest_framework.renderers import JSONRenderer
class Test2(APIView):
# 局部配置
renderer_classes = [JSONRenderer]
def get(self, request, *args, **kwargs):
return Response('this get request is ok')
def post(self, request, *args, **kwargs):
return Response('this post request is ok')
排序渲染器类的顺序
在为
API
指定渲染器类时,要考虑清楚为每种媒体类型分配什么样的优先级,这一点很重要。如
果客户端未明确指定它可以接受的内容类型,例如发送Accept: */*
属性值,或者根本没有
Accept
属性值,那么REST
框架将选择settings
列表中的第一个渲染器用于渲染响应内容。
如果你的API
包含可根据请求的不同,同时提供常规网页和AP
I响应的视图,请使用
TemplateHTMLRenderer
作为默认渲染器。
网友评论