mediterranean
mediterranean

Reputation: 123

Conditionally return JSON or HTML response from Django django-rest-framework's view

How can you conditionally return a JSON or HTML response from Django django-rest-framework's view?

  1. djangorestframework == 2.3.10

  2. My settings.py:

REST_FRAMEWORK = {
    'PAGINATE_BY': 10,
    'DEFAULT_RENDERER_CLASSES': (
        'rest_framework.renderers.TemplateHTMLRenderer',
        'rest_framework.renderers.JSONRenderer',
    )
}
  1. In my url.py, I added this as the last line:
urlpatterns = format_suffix_patterns(urlpatterns, allowed=['json', 'html'])
  1. My view is something like:
def myview(request, id, format='json'):
    if format == 'json' or format is None:
        return Response(my_dict, status=status.HTTP_200_OK)
        else:
            return Response(my_dict, template_name='myhtml.html')

Everything works OK, if I explicitly use .html or .json format_prefix in the url request. But it gives me the following error if I don't specify any format.

ImproperlyConfigured at /objects/29
Returned a template response with no template_name attribute set on either the view or response
Request Method: GET
Request URL: localhost:8000/objects/29
Django Version: 1.7
Exception Type: ImproperlyConfigured
Exception Value: Returned a template response with no template_name attribute set on either the view or response
Exception Location: D:\WORKSPACE\user...\lib\site-

I also tried:

urlpatterns = format_suffix_patterns(urlpatterns, allowed=['json', 'html', 'None'])

But it doesn't seem to work either.

Could someone please help? Thanks!

Upvotes: 7

Views: 8507

Answers (2)

yogendra maarisetty
yogendra maarisetty

Reputation: 380

After research this worked for me Below django view acts as template renderer and json renderer

views.py

from rest_framework.renderers import JSONRenderer, TemplateHTMLRenderer
from rest_framework.decorators import api_view, renderer_classes
from django.http.response import JsonResponse
from django.shortcuts import render


@api_view(['GET','POST'])
@renderer_classes([JSONRenderer,TemplateHTMLRenderer])
def myview(request, id, format='json'):
        if format == 'json' or format is None:
            return JsonResponse(my_dict, status=status.HTTP_200_OK)
        else:
            return render(request,'template_name.html',{"context":my_dict})

settings.py

REST_FRAMEWORK = {
    'DEFAULT_RENDERER_CLASSES': (
    'rest_framework.renderers.JSONRenderer',        
    'rest_framework.renderers.TemplateHTMLRenderer',
    ),
}

The above view will act like both Json renderer and Template renderer. Based on the condition you can see the behavior.

Upvotes: 1

mynameistechno
mynameistechno

Reputation: 3543

This worked for me:

class MyView(ListAPIView):
    renderer_classes = (JSONRenderer, TemplateHTMLRenderer,)

    def get(self, request, *args, **kwargs):
        data = SomerSerializer([]).data
        if request.accepted_renderer.format == 'html':
            return Response(data, template_name='blah.html')

        return Response(data)

FYI I've gotten this error before, but it wasn't because it was configured properly - it was because some unrelated code right before it errored out - so look for anything else that might be failing. Also note that your 'else' is redundant.

Upvotes: 6

Related Questions