Search code examples
djangomixinsdjango-class-based-viewsdjango-generic-views

error: view didn't return HttpResponse object in generic class based views using mixin in Django?


I am writing a mixin that would enable for partial saving of form. For more details on this, please see my previous post.. while that is fixed, I have another error. I think the error comes from post method of mixing for not returnig HttpResponse Object. I am doing a super call which should take care of that. But that didn't work.

Error:

Exception Type:     ValueError
Exception Value:    The view blog.views.ArticleCreateView didn't return an HttpResponse object.

Here is the mixin:

class PendFormMixin(object):
    form_hash_name = 'form_hash'
    pend_button_name = 'pend'
    def get_form_kwargs(self):
        """
        Returns a dictionary of arguments to pass into the form instantiation.
        If resuming a pended form, this will retrieve data from the database.
        """
        form_hash = self.kwargs.get(self.form_hash_name)
        print "form_hash", form_hash
        if form_hash:
            import_path = self.get_import_path(self.get_form_class())
            return {'data': self.get_pended_data(import_path, form_hash)}
        else:
            print "called"
            # print super(PendFormMixin, self).get_form_kwargs()
            return super(PendFormMixin, self).get_form_kwargs()

    def post(self, request, *args, **kwargs):
        """
        Handles POST requests with form data. If the form was pended, it doesn't follow
        the normal flow, but saves the values for later instead.
        """
        self.object = None
        if self.pend_button_name in self.request.POST:
            print "here"
            form_class = self.get_form_class()
            print form_class
            form = self.get_form(form_class)
            # print "form is ", form
            self.form_pended(form)
            super(PendFormMixin, self).post(request, *args, **kwargs)
        else:
            super(PendFormMixin, self).post(request, *args, **kwargs)

# Custom methods follow
    def get_import_path(self, form_class):
        return '{0}.{1}'.format(form_class.__module__, form_class.__name__)

    def get_form_hash(self, form):
        content = ','.join('{0}:{1}'.format(n, form.data[n]) for n in form.fields.keys())
        return md5(content).hexdigest()

    def form_pended(self, form):
        import_path = self.get_import_path(self.get_form_class())
        form_hash = self.get_form_hash(form)
        print "in form_pended"
        pended_form = PendedForm.objects.get_or_create(form_class=import_path,
                                                       hash=form_hash)
        print "form_class", import_path
        print "form_hash", form_hash
        print "pended_form", pended_form
        for name in form.fields.keys():
            pended_form[0].data.get_or_create(name=name, value=form.data[name])
        print pended_form[0]
        return form_hash

    def get_pended_data(self, import_path, form_hash):
        data = PendedValue.objects.filter(import_path=import_path, form_hash=form_hash)
        return dict((d.name, d.value) for d in data)

Here is the View:

class ArticleCreateView(PendFormMixin, CreateView):
      form_class = ArticleForm
      model = Article
      template_name = "article_create.html"
      success_url = '/admin'

      def form_valid(self, form):
        """
        If the request is ajax, save the form and return a json response.
        Otherwise return super as expected.
        """
        if self.request.is_ajax():
            self.object = form.save()
            time.sleep(5)
            return HttpResponse(json.dumps("success"),
                mimetype="application/json")
        return super(ArticleCreateView, self).form_valid(form)

      def form_invalid(self, form):
        """
        We haz errors in the form. If ajax, return them as json.
        Otherwise, proceed as normal.
        """
        if self.request.is_ajax():
            return HttpResponseBadRequest(json.dumps(form.errors),
                mimetype="application/json")
        return super(ArticleCreateView, self).form_invalid(form)

Solution

  • The post method of a Class-Based View should return a HttpResponse object (as the exception says, obviously). In your mixin, you forgot to return something, hence the error. You just need to return the result from CreateView, from your super() call:

    def post(self, request, *args, **kwargs):
        """
        Handles POST requests with form data. If the form was pended, it doesn't follow
        the normal flow, but saves the values for later instead.
        """
        self.object = None
        if self.pend_button_name in self.request.POST:
            # You do things there
    
        # It is the same line, you don't need an else block then. Note the "return"
        return super(PendFormMixin, self).post(request, *args, **kwargs)