5

I have sub-classed Generic DetailView class in views.py and trying to figure out a way to return data in JSON format based on an argument received in the url. Here's what I have tried doing...

# views.py
from django.views.generic import DetailView
from django.http import JsonResponse    

class ExtendedView(DetailView):
    context_object_name = 'post'
    model = StorageModel
    template_name='posts.html'
    
    def get_context_data(self, **kwargs):
        data = super(HacksViewPost, self).get_context_data(**kwargs)
        if bool(self.request.GET):
            data__ = JsonForm(request.GET)
            if data__.is_valid():
                json = data__.cleaned_data['json']
                if json == 'true':
                    return JsonResponse({'data': 'data'})
        return data

But this gave me TypeError as it should be:

TypeError at /category/extended-slug/
context must be a dict rather than JsonResponse.

The url that activates the ExtendedView class is:

/category/extended-slug?json=true

So, the question is how could i send data in JSON Format from a Generic View Class and are there any better ways of acheiving this?

2 Answers 2

10

I think you patch it at the wrong level. The get_context_data is used by the get function to render it. As a result, the get_context_data object has no control about what is done with the result, in order to construct a server response,

You can however patch the get(..) function like:

class ExtendedView(DetailView):

    """A base view for displaying a single object."""
    def get(self, request, *args, **kwargs):
        self.object = self.get_object()
        data = self.get_context_data(object=self.object)
        if self.request.GET:
            data__ = JsonForm(request.GET)
            if data__.is_valid():
                json = data__.cleaned_data['json']
                if json == 'true':
                    return JsonResponse({'data': data})
        return self.render_to_response(data)

The same holds for post, put, and other requests.

If we take a look at the DetailView source code we see:

class BaseDetailView(SingleObjectMixin, View):
    """A base view for displaying a single object."""
    def get(self, request, *args, **kwargs):
        self.object = self.get_object()
        context = self.get_context_data(object=self.object)
        return self.render_to_response(context)

Hence the get(..) calls the get_context_data(..) function. But it does not immediately returns the result, it wraps it into a rendered response.

Sign up to request clarification or add additional context in comments.

1 Comment

Exactly, what i was looking for.
2

You can't return a JsonResponse inside the get_context_data method. The get_context_data method allows you to send extra information (context) to the template and is expected to return a dict, not a JsonResponse.

If you want to return a JsonResponse, do that in the get or post method of your class.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.