Emmanuel Mtali
Emmanuel Mtali

Reputation: 4983

CourseModuleUpdateView didn't return an HttpResponse object. It returned None instead

I have the following class for displaying related course module using formsets

class CourseModuleUpdateView(TemplateResponseMixin, View):
    template_name = 'courses/manage/module/formset.html'
    course = None

    def get_formset(self, data=None):
        return ModuleFormSet(instance=self.course, data=data)

    def dispatch(self, request, *args, **kwargs):
        self.course = get_object_or_404(Course,
                                        id=kwargs['pk'],
                                        owner=request.user)
        super(CourseModuleUpdateView, self).dispatch(request, *args, **kwargs)

    def get(self, request, *args, **kwargs):
        formset = self.get_formset()
        return self.render_to_response({'course': self.course, 'formset': formset})

Url pattern responsible for this CBV

url(r'^(?P<pk>\d+)/module/$', views.CourseModuleUpdateView.as_view(), name='course_mudule_update')

Issuing a get request I get the following error

Traceback:

File "/home/mtali/.virtualenvs/educa/lib/python3.5/site-packages/django/core/handlers/exception.py" in inner
  41.             response = get_response(request)

File "/home/mtali/.virtualenvs/educa/lib/python3.5/site-packages/django/core/handlers/base.py" in _get_response
  198.                 "returned None instead." % (callback.__module__, view_name)

Exception Type: ValueError at /courses/4/module/ Exception Value: The view courses.views.CourseModuleUpdateView didn't return an HttpResponse object. It returned None instead.

What is wrong with my code! I am using django 1.11

Upvotes: 0

Views: 171

Answers (1)

user459872
user459872

Reputation: 24897

As per the Django documentation dispatch method should return a HTTP response.

dispatch(request, *args, **kwargs)

The view part of the view – the method that accepts a request argument plus arguments, and returns a HTTP response.

Explanation based on your code.

From the source code of Django View class,

def dispatch(self, request, *args, **kwargs):
        # Try to dispatch to the right method; if a method doesn't exist,
        # defer to the error handler. Also defer to the error handler if the
        # request method isn't on the approved list.
        if request.method.lower() in self.http_method_names:
            handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
        else:
            handler = self.http_method_not_allowed
        return handler(request, *args, **kwargs)

dispatch method is not only delegates the requested method to the corresponding handler it also returns back the handler response.

i.e., In this line.

return handler(request, *args, **kwargs)

In your case you are invoking super(CourseModuleUpdateView, self).dispatch(request, *args, **kwargs) in your dispatch method, this will invoke the superclass's dispatch method(i.e., View class dispatch method). Since your requested http method is GET after executing the following line on the dispatch method

handler = getattr(self, request.method.lower(), self.http_method_not_allowed)

handler will be assigned to get. So in this case it is roughly equivalent to

def dispatch(self, request, *args, **kwargs):
    return get(request, *args, **kwargs)

This get will invoke the get method in your CourseModuleUpdateView class i.e.,

def get(self, request, *args, **kwargs):
        formset = self.get_formset()
        return self.render_to_response({'course': self.course, 'formset': formset})

Which returns a valid HTTP response.

This response will reach the place where the get method is called. i.e., Inside Views dispatch method. And from there it will return the response from where it is invoked i.e., super(CourseModuleUpdateView, self).dispatch(request, *args, **kwargs). Since your not returning response that you received from the dispatch method resulting in

Exception Type: ValueError at /courses/4/module/ Exception Value: The view courses.views.CourseModuleUpdateView didn't return an HttpResponse object. It returned None instead.

Upvotes: 0

Related Questions