rahul
rahul

Reputation: 366

Django class based views: Posting form data returns 302 Found status code

I'm using django's generic class based view CreateView to upload images to a book. Here's the code:

# models.py
class Upload(models.Model):
    image = models.ImageField(upload_to=get_upload_path, help_text='Image to process')
    uploader = models.ForeignKey(settings.AUTH_USER_MODEL, models.CASCADE, related_name='uploader')
    language = models.ForeignKey(Language, models.CASCADE)
    book = models.ForeignKey(Book, models.CASCADE)

    def __str__(self):
        return str(os.path.split(self.image.name)[-1].split('_', 1)[-1])

    @models.permalink
    def get_absolute_url(self):
        return ('book:upload_new', (self.book.id,))     # upload_new is linked to the view below

    def save(self, *args, **kwargs):
        super(Upload, self).save(*args, **kwargs)

    def delete(self, *args, **kwargs):
        self.image.delete(False)
        super(Upload, self).delete(*args, **kwargs)


# views.py
@method_decorator(login_required, name='dispatch')
class PictureCreateView(CreateView):
    model = Upload
    fields = ("image",)
    book_id = None

    def dispatch(self, *args, **kwargs):
        # book_id is passed as a URL parameter
        self.book_id = self.kwargs['book_id']
        return super().dispatch(*args, **kwargs)

    def get_context_data(self, **kwargs):
        context = super(PictureCreateView, self).get_context_data(**kwargs)
        context['book_id'] = self.book_id
        return context

    def form_valid(self, form, **kwargs):
        book = Book.objects.get(id=self.book_id)
        form.instance.book = book
        form.instance.language = book.language
        form.instance.uploader = self.request.user
        self.object = form.save()

        # Running the command below prints
        # <TemplateResponse status_code=200, "text/html; charset=utf-8">
        # implying the upload was successful
        #
        # print(self.render_to_response(context=self.get_context_data()))

        return super(PictureCreateView, self).form_valid(form)

    def form_invalid(self, form):
        print(form.errors)
        data = json.dumps(form.errors)
        return HttpResponse(content=data, status=400, content_type='application/json')

When I'm trying to upload an image, I get a 302 Found error for this request (as seen in the my browser's dev tools) implying the page has moved temporarily. Apart from the headers, I'm unable to see a preview or response for this request. The upload was successful though (I checked in the admin page).

Someone had this issue before and the answer pointed out an error in the URL conf. However, the issue wasn't fully resolved and the OP still got a 302 status code.

What could be the reason for this?

Upvotes: 4

Views: 3530

Answers (1)

luc
luc

Reputation: 43096

By default form_valid method redirects with 302 code to the success_url (which can be generated dynamically by overriding get_success_url) . So this is the normal behavior and I think a good practice. So I would not change it.

But if you really want to, you can return any other response code, for example : a 200 code with similar content than the get

# views.py
@method_decorator(login_required, name='dispatch')
class PictureCreateView(CreateView):
    ...

    def form_valid(self, form, **kwargs):
        book = Book.objects.get(id=self.book_id)
        form.instance.book = book
        form.instance.language = book.language
        form.instance.uploader = self.request.user
        self.object = form.save()

        context = self.get_context_data()
        # You may have check and modify your context for a correct page
        # May be: add new things
        context["success"] = True

        return self.render_to_response(context))

Upvotes: 7

Related Questions