Reputation: 1835
I have a custom Django view class that inherits from the generic DetailView
.
The generic DetailView
class sequentially calls its methods get_queryset
, get_object
, and others to generate an object to pass for a Django template.
Moreover, the generic DetailView
class raises Http404
exception within these methods to deal with erroneous situations #.
except queryset.model.DoesNotExist:
raise Http404(_("No %(verbose_name)s found matching the query") %
{'verbose_name': queryset.model._meta.verbose_name})
What I am trying to do is simple: I want to return other HTTP status codes to the client if an error is found within these methods. However, because Http404
is the only Django HttpResponse
that has a form of exception, it seems like this cannot be achieved easily.
Because HttpResponse
is not an exception, I have to return it instead of raising it. Therefore, the customized method becomes the following form.
def get_object(self, queryset=None):
...
try:
# Get the single item from the filtered queryset
obj = queryset.get()
except queryset.model.DoesNotExist:
return HttpResponseBadRequest("Bad request.")
However, above code does not send HttpResponseBadRequest
to the client. Instead, it returns HttpResponseBadRequest
as an object for a Django template. The client gets 200 status code with an invalid object for the template.
The only possible solution to think is writing some object-checking code within the Django template. However, I wonder if there is any better way to deal with this problem.
Upvotes: 3
Views: 1369
Reputation: 21807
Since Django 3.2 we now have an exception BadRequest
[Django docs] which will be turned into a HttpResponseBadRequest
internally when caught, so you can try catching Http404
and raising BadRequest
instead:
from django.core.exceptions import BadRequest
class MyView(SomeGenericView):
...
def get_object(self, queryset=None):
try:
return super().get_object(queryset=queryset)
except Http404 as e:
# raise BadRequest("Bad request.") from e
raise BadRequest("Bad request.")
For some previous version we can try to catch the exception at the dispatch
method and return the appropriate response there:
class MyView(SomeGenericView):
...
def dispatch(self, request, *args, **kwargs):
try:
return super().dispatch(request, *args, **kwargs)
except Http404:
return HttpResponseBadRequest("Bad request.")
Upvotes: 1