渲染模板
根据用户请求的RUL向服务器要响应的数据类型,比如:json数据,xml数据,将这些数据向用户返回
一、渲染模板的使用
# 在renderers.py模板模块中导入你要渲染的模板
# JSONRenderer: 返回json数据
# BrowsableAPIRenderer: 返回浏览器html页面
from rest_framework.renderers import JSONRenderer, BrowsableAPIRenderer
# 1.局部配置
# 渲染模块的局部配置
# 局部禁用就是配置空list:[] # pytthon3.7 有问题
renderer_classes = [JSONRenderer, BrowsableAPIRenderer]
# 2.全局配置
# drf的配置,在drf中settings.py查看如何配置
REST_FRAMEWORK = {
# 渲染模块的全局配置:开发一般只配置json
'DEFAULT_RENDERER_CLASSES': [
'rest_framework.renderers.JSONRenderer',
'rest_framework.renderers.TemplateHTMLRenderer',
],
}
二、渲染模板的源码解析
# 1 对请求响应进行二次封装
def dispatch(self, request, *args, **kwargs):
....
....
# 二次处理响应
self.response = self.finalize_response(request, response, *args, **kwargs)
return self.response
# 2. 接续配置的渲染类
def finalize_response(self, request, response, *args, **kwargs):
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()
# 3. 获取渲染对象的类
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
# 3 renderer_classes 自己全局
def get_renderers(self):
"""
Instantiates and returns the list of renderers that this view can use.
"""
# 从自己的视图类找renderer_classer类属性(局部配置)APIView的类属性(从自己配置文件中找)> 自己的项目配置文件中找(全局配置), drf默认配置问价中找(默认配置)
return [renderer() for renderer in self.renderer_classes]
class BaseRenderer:
"""
All renderers should extend this class, setting the `media_type`
and `format` attributes, and override the `.render()` method.
"""
media_type = None
format = None
charset = 'utf-8'
render_style = 'text'
def render(self, data, accepted_media_type=None, renderer_context=None):
raise NotImplementedError('Renderer class requires .render() to be implemented')
总结:
- 根据流程,再次进入drf的dispatch方法,该方法对响应数据进行了二次封装,然后,进入self.finalize_response方法
- 在self.finalize_respons方法中perform_content_negotiation中获取渲染的对象结果,进入perform_content_negotiation方法
- perform_content_negotiation方法中实现了获取配置文件的渲染结果集,通过self.get_renderers()方法
- 在self.get_renderers()方法中self.renderer_classes读取配置的渲染对象,先从创建的视图类中(BookAPIView(APIView)(局部配置))找,然后在从自己的项目文件中找(项目中 settings.py,全局配置), 最后从drf默认配置文件中(默认配置)
- renderer()是从配置文件中获取到的对应类然后到 renderer.py 文件中获取类对象,创建的类对象(JSONRenderer())返回数据渲染的结果
- 核心:可以全局和局部配置视图类支持的结果渲染:默认可以json和页面渲染,学习该模块的目的是开发可以全局只配置json方式渲染