从2013年开始this ticket表示:
。当在ViewSet内部时,将设置.action属性,以触发任何一个动作(例如列表)。如果你在一个方法中,例如get_template_names,你可以使用它,并且需要访问正在处理的任何一个动作。
但是,当我尝试进行一个简单的实验时:
class ExampleViewSet(viewsets.ModelViewSet):
"""
A viewset for the example model.
"""
queryset = Example.objects.all()
serializer_class = ExampleSerialiser
def get_template_names(self):
if self.action == 'list':
return ['example/list_examples.html']
使用设置:
REST_FRAMEWORK = {
'DEFAULT_RENDERER_CLASSES': (
'rest_framework.renderers.TemplateHTMLRenderer',
'rest_framework.renderers.BrowsableAPIRenderer',
'rest_framework.renderers.JSONRenderer'
),
}
我明白了:
Internal Server Error: /example/
Traceback (most recent call last):
File "/usr/local/lib/python2.7/dist-packages/django/core/handlers/exception.py", line 39, in inner
response = get_response(request)
File "/usr/local/lib/python2.7/dist-packages/django/core/handlers/base.py", line 217, in _get_response
response = self.process_exception_by_middleware(e, request)
File "/usr/local/lib/python2.7/dist-packages/django/core/handlers/base.py", line 215, in _get_response
response = response.render()
File "/usr/local/lib/python2.7/dist-packages/django/template/response.py", line 109, in render
self.content = self.rendered_content
File "/usr/local/lib/python2.7/dist-packages/rest_framework/response.py", line 72, in rendered_content
ret = renderer.render(self.data, accepted_media_type, context)
File "/usr/local/lib/python2.7/dist-packages/rest_framework/renderers.py", line 174, in render
return template_render(template, context, request=request)
File "/usr/local/lib/python2.7/dist-packages/rest_framework/compat.py", line 279, in template_render
return template.render(context, request=request)
File "/usr/local/lib/python2.7/dist-packages/django/template/backends/django.py", line 64, in render
context = make_context(context, request, autoescape=self.backend.engine.autoescape)
File "/usr/local/lib/python2.7/dist-packages/django/template/context.py", line 267, in make_context
context.push(original_context)
File "/usr/local/lib/python2.7/dist-packages/django/template/context.py", line 59, in push
return ContextDict(self, *dicts, **kwargs)
File "/usr/local/lib/python2.7/dist-packages/django/template/context.py", line 18, in __init__
super(ContextDict, self).__init__(*args, **kwargs)
ValueError: dictionary update sequence element #0 has length 4; 2 is required
从浏览源代码看,get_template_names似乎会返回一个可迭代的。
我做错了什么?
将Django升级到最新版本会将异常更改为更明显的类型:TypeError:
Internal Server Error: /example/
Traceback (most recent call last):
File "/usr/local/lib/python2.7/dist-packages/django/core/handlers/exception.py", line 41, in inner
response = get_response(request)
File "/usr/local/lib/python2.7/dist-packages/django/core/handlers/base.py", line 217, in _get_response
response = self.process_exception_by_middleware(e, request)
File "/usr/local/lib/python2.7/dist-packages/django/core/handlers/base.py", line 215, in _get_response
response = response.render()
File "/usr/local/lib/python2.7/dist-packages/django/template/response.py", line 107, in render
self.content = self.rendered_content
File "/usr/local/lib/python2.7/dist-packages/rest_framework/response.py", line 72, in rendered_content
ret = renderer.render(self.data, accepted_media_type, context)
File "/usr/local/lib/python2.7/dist-packages/rest_framework/renderers.py", line 176, in render
return template_render(template, context, request=request)
File "/usr/local/lib/python2.7/dist-packages/rest_framework/compat.py", line 340, in template_render
return template.render(context, request=request)
File "/usr/local/lib/python2.7/dist-packages/django/template/backends/django.py", line 64, in render
context = make_context(context, request, autoescape=self.backend.engine.autoescape)
File "/usr/local/lib/python2.7/dist-packages/django/template/context.py", line 287, in make_context
raise TypeError('context must be a dict rather than %s.' % context.__class__.__name__)
TypeError: context must be a dict rather than ReturnList.
[09/Jul/2017 13:22:26] "GET /example/ HTTP/1.1" 500 91963
上下文似乎是OrderedDicts数组:
/usr/local/lib/python2.7/dist-packages/rest_framework/compat.py in template_render
return template.render(context, request=request) ...
▼ Local vars
context [OrderedDict([(u'url', u'http://127.0.0.1:8080/example/1/'), ('created', u'2017-06-26T19:48:08.980344Z'), ('updated', u'2017-07-08T21:54:28.505181Z'), ('name', u'Example 1')]), OrderedDict([(u'url', u'http://127.0.0.1:8080/example/2/'), ('created', u'2017-06-26T21:45:36.310536Z'), ('updated', u'2017-06-26T21:45:36.310636Z'), ('name', u'Example 2')]), OrderedDict([(u'url', u'http://127.0.0.1:8080/example/3/'), ('created', u'2017-06-26T21:46:00.390582Z'), ('updated', u'2017-06-26T21:46:00.390620Z'), ('name', u'Example 3')]), OrderedDict([(u'url', u'http://127.0.0.1:8080/example/4/'), ('created', u'2017-06-26T21:46:07.777296Z'), ('updated', u'2017-06-26T21:46:07.777335Z'), ('name', u'Example 4')])]
request <rest_framework.request.Request object at 0x7f027aa31cd0>
templat <django.template.backends.django.Template object at 0x7f027aa31190>
似乎情况正在发生。
所以,我最初认为这与get_template_names有关,这是错误的。显然它与它无关。这似乎与使用ViewHTets和TemplateHTMLRenderer有关。这是否按预期工作?
来自docs:
TemplateHTMLRenderer类要求响应包含上下文数据字典,并根据必须在视图或响应中指定的模板呈现HTML页面。
StaticHTMLRender类要求响应包含一个字符串 预呈现的HTML内容。
因为静态HTML页面通常具有与API不同的行为 您可能需要明确地编写任何HTML视图的响应, 而不是依赖于内置的通用视图。
对于我所知道的记录,并且一直在使用覆盖方法的格式,如:
def list(self, request, **kwargs):
if request.accepted_renderer.format == 'html':
examples = {'examples': self.get_queryset()}
return Response(examples, template_name='example/list_examples.html')
return super(ExampleViewSet, self).list(self, request, **kwargs)
但是,我原本以为这主要是为了明确你要在视图上呈现哪个模板。为了避免覆盖所有这些方法,我希望使用get_template_names方法。