使用DRF ModelViewSet和TemplateHTMLRenderer时,如何访问模板中的数据?

时间:2013-09-20 20:30:31

标签: django django-rest-framework

我有一个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

所以我必须要错过一些简单的事情,或者我期望这样做是不是作者的意图?

4 个答案:

答案 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的回答也给出了最好的例子。