我有一个Django Rest Framework ModelViewSet
,我正在尝试使用TemplateHTMLRenderer
来显示HTML。跟随tutorial:
from rest_framework import permissions, renderers, viewsets
from rest_framework.decorators import link
from . import models, serializers
from .permissions import IsOwnerOrReadOnly
class SnippetViewSet(viewsets.ModelViewSet):
template_name = 'snippet-list.html'
queryset = models.Snippet.objects.all()
serializer_class = serializers.SnippetSerializer
renderer_classes = (renderers.TemplateHTMLRenderer,)
permission_classes = (permissions.IsAuthenticatedOrReadOnly,
IsOwnerOrReadOnly,)
@link(renderer_classes=[renderers.StaticHTMLRenderer])
def highlight(self, request, *args, **kwargs):
snippet = self.get_object()
return Response(snippet.highlighted)
def pre_save(self, obj):
obj.owner = self.request.user
如果我在def resolve_context()
中添加密钥,我可以访问模板中传递给RequestContext
的模型对象。如果我不添加data
密钥,那么我不知道如何访问代码段。
def resolve_context(self, data, request, response):
if response.exception:
data['status_code'] = response.status_code
#return RequestContext(request, data) # original source on github
return RequestContext(request, {'data': data}) # if I add a key I can access it
所以我必须要错过一些简单的事情,或者我期望这样做是不是作者的意图?
答案 0 :(得分:12)
我会这样:
class SnippetViewSet(viewsets.ModelViewSet):
queryset = Snippet.objects.all()
serializer_class = SnippetSerializer
renderer_classes = (renderers.JSONRenderer, renderers.TemplateHTMLRenderer)
def list(self, request, *args, **kwargs):
response = super(SnippetViewSet, self).list(request, *args, **kwargs)
if request.accepted_renderer.format == 'html':
return Response({'data': response.data}, template_name='home.html')
return response
并使用http://127.0.0.1:8000/snippets/.html
获取表格(或您使用的任何后缀)。
这样您就不会为每种渲染类型覆盖解析器。
其他解决方案是仅为列表操作创建专用视图,并仅使用HTML渲染器。但是你会有一个小代码重复。
答案 1 :(得分:0)
我也遇到了同样的问题,我也这么认为。我来到谷歌。我不喜欢覆盖“def list(self,request,* args,** kwargs):”,因为我觉得它打破了viewset的设计理念。在我研究了“site-packages \ rest_framework”中的代码片段教程和源代码之后,我得到了密钥,而不是viewset而是“serializer.data”。在“site-packages \ rest_framework \ serializers.py”中,我找到了类BaseSerializer,即ModelSerializer的顶级基类。其属性“数据”定义如下:
@property
def data(self):
... # omitted the function body here, because it didn't care about this solution.
return self._data
此属性数据只是“serializer.data”,它只是传递给模板的响应。所以我只是覆盖了“snippets / serializers.py”中的data属性,并在调用了father的方法之后,为返回的数据设置了密钥:
class SnippetSerializer(serializers.ModelSerializer):
@property
def data(self):
return { 'data' : super(serializers.ModelSerializer, self).data } #'data' can be replaced with other wanted name.
class Meta:
model = Snippet
fields = ('id', 'title', 'code', 'linenos', 'language', 'style')
好的,在模板中使用“数据”这个名称。
答案 2 :(得分:0)
我对提供模板上下文的方法进行了子类化和覆盖,以便序列化数据在模板上下文中的data
下可用:
from rest_framework.renderers import TemplateHTMLRenderer
class MyHTMLRenderer(TemplateHTMLRenderer):
def get_template_context(self, data, renderer_context):
context = {'data': data}
response = renderer_context['response']
if response.exception:
data['status_code'] = response.status_code
return context
答案 3 :(得分:0)
在视图集内使用渲染器类
renderer_classes =(renderers.JSONRenderer,renderers.TemplateHTMLRenderer)
如上所述,并覆盖 ListModelMixin 的列表方法。
mariodev的回答也给出了最好的例子。