Django Rest Framework:如果没有找到结果,则回复404

时间:2018-06-03 10:21:55

标签: django django-rest-framework

在这里的其他一些人的帮助下,我设法让我的DRF驱动的API达到了一个好处。我现在试图搞清楚一些细节。目前。

以下是观点:

class EpisodeViewSet(viewsets.ModelViewSet):
    queryset = Episode.objects.all().order_by('-published_at')
    filter_backends = (DjangoFilterBackend,)
    filter_fields = ('show_id', 'number')

    def get_serializer_class(self):
        if self.action == 'retrieve':
            return EpisodeDetailSerializer
        if self.request.GET.get('show_id') and self.request.GET.get('number'):
            return EpisodeDetailSerializer
        return EpisodeSerializer

这是我的序列化器:

class EpisodeDetailSerializer(serializers.ModelSerializer):
    chapters = ChapterMarkSerializer(source='chaptermark_set', many=True)
    media = MediaClipSerializer(source='mediaclip_set', many=True)
    show = ShowSerializer()
    guest = GuestSerializer(source='guest_set', many=True, read_only=True)
    topic = TopicSerializer(source='topic_set', many=True, read_only=True)

    # def get_queryset(self):
    #    show = self.request.query_params.get('show')
    #    number = self.request.query_params.get('number')
    #    queryset = self.objects.get(show_id=show, number=number)
    #    return queryset

    class Meta:
        model = Episode
        fields = ('id', 'title', 'number', 'subtitle', 'show', 'published_at', 'updated_at', 'description_title',
                  'description', 'show_notes', 'supporters_title', 'supporters_text', 'supporters_button',
                  'forum_title', 'forum_text', 'forum_link', 'cover_image', 'updated_at', 'chapters', 'media',
                  'guest', 'topic')
        depth = 1

我不确定get_queryset函数来自何处,但结果奇怪的是有没有,这就是为什么它现在被注释掉了。

背景是我以两种不同的方式查询剧集:

  1. 通过他们的主键api/episodes/123
  2. 通过show和number api/episodes?show_id=1&number=2
  3. 过滤

    在第一种情况下,如果找到,则api返回一个对象,或者只返回包含

    的对象的404
    {
        "detail": "Not found."
    }
    

    如果有该ID的剧集不存在。

    在第二种情况下,它返回一个对象列表(旁注:我更喜欢也只获得一个对象,因为永远不会有多个结果,但这可能是一个不同的主题)。如果没有找到任何内容,它仍会返回HTTP 200的空结果。

    为了在前端进行更清洁的处理,如果在两种情况下都找不到任何内容,我更愿意提出HTTP 404。我已经发现这可能适用于尝试/除了Django,但我还没有成功找到放置它的位置。我仍然只是用DRF刮擦表面。

    感谢任何帮助。

2 个答案:

答案 0 :(得分:2)

我认为最简单的方法(也许是最常用的)将覆盖ModelViewSet的list()方法。这是代码(来自mixins.py):

def list(self, request, *args, **kwargs):
    queryset = self.filter_queryset(self.get_queryset())

    page = self.paginate_queryset(queryset)
    if page is not None:
        serializer = self.get_serializer(page, many=True)
        return self.get_paginated_response(serializer.data)

    serializer = self.get_serializer(queryset, many=True)
    return Response(serializer.data)

以上是原始代码。然后,您可以在类中覆盖它,例如,您可以添加以下行(在queryset =之后和page =之前)

  ...
 if queryset.count():
    raise exceptions.NotFound()
 ...

实际上,你现在可以做你想做的事。您还可以更改函数以返回单个对象。

答案 1 :(得分:1)

您可以为此覆盖viewset的list方法:

from rest_framework import status
from rest_framework.response import Response

def list(self, request, *args, **kwargs):
    queryset = self.filter_queryset(self.get_queryset())
    if not queryset.exists():
        return Response({"detail": "Not found."}, status=status.HTTP_404_NOT_FOUND)

    page = self.paginate_queryset(queryset)
    if page is not None:
        serializer = self.get_serializer(page, many=True)
        return self.get_paginated_response(serializer.data)

    serializer = self.get_serializer(queryset, many=True)
    return Response(serializer.data)