django rest framework manually display 404 page
<p>So I have typical generic view:</p>

<pre><code>class FooListAPIView(generics.ListAPIView):
    serializer_class = FooSerializer
    lookup_fields = ('area_id', 'category_id', )

    def get_queryset(self):
        area = Area.objects.get(pk=self.kwargs.get('area_id'))
        area_tree = area.get_tree(parent=area) #returns queryset 
        category = Category.objects.get(pk=self.kwargs.get('category_id'))
        queryset = Foo.objects.filter(area__in=area_tree, category=category)
        return queryset

    def get_object(self):
        queryset = self.get_queryset()
        queryset = self.filter_queryset(queryset)
        filter = {}
        for field in self.lookup_fields:
            filter[field] = self.kwargs[field]
        return get_object_or_404(queryset, **filter)
</code></pre>

<p>My problem is, if i try get area or category objects, which doesn't exist, browser throws me error: </p>

<blockquote>
  <p>Area matching query does not exist.</p>
</blockquote>

<p>How can I make it so, that when Area matching query does not exist, I get standard rest framework 404 response?</p>

<p>The problem here is that <code>get_queryset</code> doesn't really expect any failures. In your case, although you are returning a queryset, you seem to be hitting the database with the <code>Area.objects.get(pk=self.kwargs.get('area_id'))</code> call. When this fails, it violates the I/O defined by <code>get_queryset</code> which isn't expecting the <code>Area.DoesNotExist</code> exception. So it fails and you end up with a Django 500 error.</p>

<p>What you need to ensure is that the <code>get_queryset</code> method, returns a queryset, preferably without making any calls to the DB (I say preferably, since there is no such rule that says it shouldn't hit the DB, but its generally understood that get_queryset wont be the one to actually perform the DB query). Then if you must, you can freely perform any get operations on your DB inside the <code>get_object</code> with the <code>get_object_or_404</code> shortcut. Since <code>get_object_or_404</code> raises an <code>Http404</code> exception and <code>get_object</code> knows how to handle this exception, it will gracefully return the 404 page that you are expecting.</p>

<p>If you can ensure your <code>area.get_tree</code> implementation can work with a parent queryset, instead of a parent object, then you could do something like this:</p>

<pre><code>class FooListAPIView(generics.ListAPIView):
    serializer_class = FooSerializer
    lookup_fields = ('area_id', 'category_id', )

    def get_queryset(self):
        area = Area.objects.filter(pk=self.kwargs.get('area_id'))
        area_tree = area.get_tree(parent=area) #returns queryset 
        category = Category.objects.filter(pk=self.kwargs.get('category_id'))
        queryset = Foo.objects.filter(area__in=area_tree, category__in=category)
        return queryset

    def get_object(self):
        queryset = self.get_queryset()
        queryset = self.filter_queryset(queryset)
        filter = {}
        for field in self.lookup_fields:
            filter[field] = self.kwargs[field]
        return get_object_or_404(queryset, **filter)
</code></pre>

<p>If you are unable to get <code>area.tree</code> to work without a queryset, then you can delay some of your <code>get_queryset</code> logic to <code>get_object</code>. Like so:</p>

<pre><code>from django.http import Http404

class FooListAPIView(generics.ListAPIView):
    serializer_class = FooSerializer
    lookup_fields = ('area_id', 'category_id', )
    queryset = Foo.objects.all()

    def get_object(self):
        queryset = self.get_queryset()
        queryset = self.filter_queryset(queryset)
        area = get_object_or_404(Area, **{'pk': self.kwargs.get('area_id')})
        area_tree = area.get_tree(parent=area)
        category = get_object_or_404(Category, **{'pk': self.kwargs.get('category_id')})
        queryset = queryset.filter(area__in=area_tree, category=category)
        filter = {}
        for field in self.lookup_fields:
            filter[field] = self.kwargs[field]
        return get_object_or_404(queryset, **filter)
</code></pre>

python django django-rest-framework