How do you access data in a template when using the DRF ModelViewSet and TemplateHTMLRenderer?

I have a Django Rest Framework ModelViewSet and I'm trying to use TemplateHTMLRenderer to render HTML. Following in the 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 

If I add the key to def resolve_context() , I can access the model objects in my template that are passed to RequestContext . If I do not add the data key, then I do not know how to access the fragments.

 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 

So, should I miss something simple or how do I expect this to behave differently than the authors suggested?

+8
django django-rest-framework
source share
4 answers

I would go as follows:

 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 

and use http://127.0.0.1:8000/snippets/.html to get the table (or whatever suffix you are using).

This way you do not override the resolver for each type of rendering.

Another solution would be to simply create a dedicated view for the list action and use only the HTML renderer. But then you will have a little code duplication.

+12
source share

I also met the same question with you, and I thought the same. I came here google. I did not like to redefine "def list (self, request, * args, ** kwargs):" because I felt like it broke the idea of โ€‹โ€‹designing the view. After I examined the tutorial and the source code for the fragment in "site-packages \ rest_framework", I got the key, not the viewet, but the "serializer.data". In "site-packages \ rest_framework \ serializers.py" I found the BaseSerializer class, i.e. Upper base class ModelSerializer. The data property is defined as follows:

 @property def data(self): ... # omitted the function body here, because it didn't care about this solution. return self._data 

These properties are just "serializer.data", which is the response passed only to the template. Therefore, I simply redefined the data property in "snippets / serializers.py", and after calling the "Father" method, I set the key for the returned data:

 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') 

OK, use the name "data" in your template.

0
source share

I have subclassed and redefined the method that provides the template context, so that serializer data is available in data in the template context:

 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 
0
source share

The rendering class is used inside the view.

renderer_classes = (renderers.JSONRenderer, renderers.TemplateHTMLRenderer)

as above, and override the ListModelMixin list method.

mariodev gives a better example.

0
source share

All Articles