在这里的其他一些人的帮助下,我设法让我的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函数来自何处,但结果奇怪的是有没有,这就是为什么它现在被注释掉了。
背景是我以两种不同的方式查询剧集:
api/episodes/123
api/episodes?show_id=1&number=2
在第一种情况下,如果找到,则api返回一个对象,或者只返回包含
的对象的404{
"detail": "Not found."
}
如果有该ID的剧集不存在。
在第二种情况下,它返回一个对象列表(旁注:我更喜欢也只获得一个对象,因为永远不会有多个结果,但这可能是一个不同的主题)。如果没有找到任何内容,它仍会返回HTTP 200的空结果。
为了在前端进行更清洁的处理,如果在两种情况下都找不到任何内容,我更愿意提出HTTP 404。我已经发现这可能适用于尝试/除了Django,但我还没有成功找到放置它的位置。我仍然只是用DRF刮擦表面。
感谢任何帮助。
答案 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)