[Django]-How to fix " '__proxy__' object has no attribute 'get' " when trying to update wrongly a form

6👍

Your form_valid and form_invalid methods can not return a lazy_reverse(..) object, since that is not a HTTP response.

You can however use redirect(..) [Django-doc], which will construct a HTTP response, like:

from django.shortcuts import redirect

class BookUpdateView(UpdateView):
    """Update the requested book."""
    model = Book
    form_class = BookForm

    # ...

    def get_success_url(self):
        messages.success(self.request, 'The book updated successfully!')
        return reverse_lazy('books:detail', kwargs = {'isbn': self.object.isbn})

    def form_invalid(self, form):
        messages.error(self.request, 'The update has failed')
        return redirect('books:index')

You can probably slightly improve your get_object method with:

from django.http import Http404
from django.shortcuts import redirect

class BookUpdateView(UpdateView):
    """Update the requested book."""
    model = Book
    form_class = BookForm

    def get_object(self):
        queryset = self.get_queryset()
        try:
            return queryset.get(isbn=self.kwargs['isbn'])
        except:
            messages.error(self.request, 'This book doesnt exist!')
            raise Http404('Book does not exist')

It is however not very common to redirect(..) in case of a form_invalid(..). Usually the template is rerendered with the form such that the form is rendered with error messages. Therefore it is not very common to override the form_invalid method: by default Django will rerender the template with the invalid form.

EDIT: you can redirect the page to another page if the isbn does not map on a valid as follows:

from django.core.exceptions import ObjectDoesNotExist
from django.http import Http404
from django.shortcuts import redirect

class BookUpdateView(UpdateView):
    """Update the requested book."""
    model = Book
    form_class = BookForm

    # ...

    def get(self, *args, **kwargs):
        try:
            self.object = self.get_object()
        except (ObjectDoesNotExist, Http404):
            return redirect('books:index')
        return self.render_to_response(self.get_context_data())

-1👍

you can also just create the reverse lazy in a variable and redirect with the variable that works perfectly fine :

instead of

return reverse_lazy('books:detail', kwargs = {'isbn': self.object.isbn})

use:

url_match = reverse_lazy('books:detail', kwargs = {'isbn': self.object.isbn})
return redirect(url_match)

Leave a comment