2016-09-07 4 views
2

だから私は典型的な汎用ビューがあります。ジャンゴ残りのフレームワークを手動404ページを表示

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) 

を私の問題は、私が存在しない領域またはカテゴリオブジェクトを取得しようとした場合、ブラウザは私にエラーをスローし、あります

Area matching query does not exist.

どのようにすれば、エリアマッチングクエリが存在しない場合でも、標準のレストフレームワーク404の応答が得られますか?

+3

'get_object_or_404()'は、あなたがすでに持っているのと同じやり方で使ってください:#query; ObjectNotFoundを除く:#404を返す – IanAuld

答えて

0

ここでの問題は、get_querysetは実際には何の失敗も期待していないということです。あなたのケースでは、クエリーセットを返していますが、Area.objects.get(pk=self.kwargs.get('area_id'))コールでデータベースにヒットしているようです。これに失敗した場合、例外を予期していないget_querysetによって定義されたI/Oに違反します。だから失敗し、あなたはDjango 500のエラーに終わる。

あなたは、get_querysetメソッドが、好ましくはDBを呼び出すことなくクエリセットを返すことを保証する必要があります(私は、DBにヒットするべきではありませんが、 get_querysetは実際にDBクエリを実行するものではないと一般的に理解されています)。次に、get_objectのショートカットでget_object_or_404を使用して、DBの取得操作を自由に実行できます。 get_object_or_404Http404例外を発生させ、get_objectはこの例外の処理方法を知っているので、期待している404ページを正常に返します。あなたがなくても動作するarea.treeを取得することができない場合

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) 

:あなたが代わりに親オブジェクトの、親クエリセットを操作することができ、あなたのarea.get_tree実施を確保することができる場合

は、その後、あなたはこのような何かを行うことができますクエリーセットでは、get_querysetロジックの一部をget_objectに遅延させることができます。ように:

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) 
関連する問題