13

So, right now when my DetailView subclass doesn't find an object using the PK (which is taken from the URL), I see the 404.html template page. What I'd rather do is just redirect to another URL. Here's my url patterns:

url(r'^(?P<pk>[0-9]+)/$', DeviceDetailView.as_view(
    template_name='devices/detail.html',
    queryset=Device.objects.all(),
    context_object_name="device",
)),
url(r'^$', FullListView.as_view(template_name='devices/devices.html',)),

So, if my url looks like /devices/8/, it uses 8 as the primary key. Works great when 8 exists in the database. However, when 8 doesn't exist, it goes to the 404 page. What I would rather it do is go to a list - in fact, the FullListView listed when last url (which is what happens when the url looks like /devices/nonnumericstuff/.

Seems like that should be pretty easy, no? I don't want all 404's to go there so i can't use handler404.

machomeautoguy
  • 587
  • 4
  • 19
  • I should mention that the urlpatterns snippet above is from a urls.py that's included from the main urls.py which is how the /devices/ part is added. – machomeautoguy Jan 11 '13 at 21:15
  • possible duplicate of [Redirect from Generic View DetailView in Django](http://stackoverflow.com/questions/6456586/redirect-from-generic-view-detailview-in-django) – Martey Oct 06 '14 at 17:19

3 Answers3

23

The DetailView's get_object method raises an Http404 exception if the object doesn't exist in the queryset. Instead of overriding the get_object method you could catch the exception in the view's get method:

from django.http import Http404
from django.views.generic import DetailView
from django.shortcuts import redirect

class MyDetailView(DetailView):

    def get(self, request, *args, **kwargs):
        try:
            self.object = self.get_object()
        except Http404:
            # redirect here
            return redirect(url)
        context = self.get_context_data(object=self.object)
        return self.render_to_response(context)
Bernhard Vallant
  • 49,468
  • 20
  • 120
  • 148
6

For common cases

from django.http import Http404
from django.shortcuts import redirect
from django.urls import reverse
from django.views.generic import DetailView


class MyDetailView(DetailView):
    def get(self, request, *args, **kwargs):
        try:
            return super().get(request, *args, **kwargs)
        except Http404:
            return redirect(reverse('my_list_view_name'))
rodion.mihan
  • 61
  • 1
  • 1
2

You should redefine def get_object(self): of the DetailView

There's something similar in this question

Community
  • 1
  • 1
msc
  • 3,780
  • 1
  • 22
  • 27
  • 1
    I found that - however, that method wants to return an object. What would I return when there is no object other than throw the 404? – machomeautoguy Jan 11 '13 at 22:05