Django get_queryset 返回 500 而不是 404

Aj1*_*Aj1 2 django django-models django-views django-rest-framework

这是我的观点:

class SampleViewSet(viewsets.ModelViewSet):
      serializer_class = SampleSerializer
      queryset = Sample.objects.all()

      def get_queryset(self):
          queryset = self.queryset
          test_code = self.request.query_params.get('test_code', None)
          if test_code is not None:
             queryset = queryset.filter(test__test_code=test_code)
          return queryset
Run Code Online (Sandbox Code Playgroud)

这是我的模型:

class Sampe(models.Model):
      test = models.OneToOneField(Test, null=True, blank=True, on_delete=models.CASCADE)
      # few more fields- not so important
Run Code Online (Sandbox Code Playgroud)

这是我的序列化程序:

class SampleSerializer(serializers.ModelSerializer):
      test_code = serializers.CharField(source='test.test_code')

      class Meta:
           model = Sample
           fields = '__all__'
Run Code Online (Sandbox Code Playgroud)

这在我点击 /api/sample?test_code="existing_param" 时有效所以当我做 /api/sample?test_code="Not_Existing_param" 时,我期望它应该抛出 404 代替,它抛出 500 测试匹配查询不存在。真的很感激任何帮助。

谢谢

Wil*_*sem 5

问题是该函数会引发错误,而 Web 服务器无法真正解释导致此错误的原因,因此通常引发 500 比引发 404 更准确。

但是你可以做的是使用 a get_list_or_404,它的作用类似于 a get_object_or_404,然后使用 a.filter(..)而不是 a .get(..)

from django.shortcuts import get_list_or_404

class SampleViewSet(viewsets.ModelViewSet):
      serializer_class = SampleSerializer
      queryset = Sample.objects.all()

      def get_queryset(self):
          queryset = self.queryset
          test_code = self.request.query_params.get('test_code', None)
          if test_code is not None:
             queryset = get_list_or_404(queryset, test__test_code=test_code)
          return queryset
Run Code Online (Sandbox Code Playgroud)

这将因此过滤查询集,并在结果查询集结果为空的情况下引发 404 异常。如果您连锁过滤器一起,就足以做到这一点的最后一个元素上,从此您检查实际的查询集将返回,从而避免检查未在后面的过程中使用了多个quersets。