DRF嵌套路由场景下无法捕获Photo.DoesNotExist异常问题求助
问题根因
- 序列化器的
create方法预期返回值为创建完成的模型实例,你在异常分支返回的Response对象会被serializer.save()当作模型实例传递到后续逻辑,无法触发正确的响应构造。 - 你重写的
perform_create方法返回Response属于无效操作:perform_create是DRF预留的创建逻辑钩子,上层的视图逻辑不会接收它的返回值作为接口响应,自定义响应需要重写create方法而非perform_create。
解决方案
方案一:在序列化器中抛出DRF标准异常(最简便)
DRF自带的异常处理器会自动将标准异常转为符合规范的HTTP响应,直接替换异常分支的返回逻辑即可:
# 先导入NotFound异常 from rest_framework.exceptions import NotFound class LikeModelSerializer(serializers.ModelSerializer): """ Like model serializer. """ user = serializers.CharField(default=serializers.CurrentUserDefault()) class Meta: """ Meta class. """ model = Like fields = ('user', 'photo') read_only_fields = ('user', 'photo') def create(self, validated_data): # Get the photo pk from the view context (DRF-nested-routers) and # create the new like with the validated_data photo_pk = self.context['view'].kwargs["photo_pk"] try: photo = Photo.objects.get(id=photo_pk) except Photo.DoesNotExist: # 抛出标准NotFound异常,不要返回Response raise NotFound(detail="The photo doesn't exist.") validated_data["photo"] = photo like, created = Like.objects.get_or_create(**validated_data) if created: photo.total_likes += 1 photo.save() return like
方案二:将存在性校验提前到视图层
如果你希望校验逻辑放在视图层,也可以重写create方法提前校验:
from rest_framework.exceptions import NotFound from rest_framework.response import Response from rest_framework import status # 重写视图的create方法,而非perform_create def create(self, request, *args, **kwargs): photo_pk = kwargs.get("photo_pk") try: Photo.objects.get(id=photo_pk) except Photo.DoesNotExist: return Response(data={'detail': "The photo doesn't exist."}, status=status.HTTP_404_NOT_FOUND) serializer = self.get_serializer(data=request.data) serializer.is_valid(raise_exception=True) self.perform_create(serializer) return Response(data=serializer.data, status=status.HTTP_200_OK) # 原来的perform_create去掉返回逻辑,只保留创建操作 def perform_create(self, serializer): """ Creates a new like. The substraction in the total_likes is made in the serializer. """ serializer.save()
内容的提问来源于stack exchange,提问作者Risker
相关产品推荐
相关产品推荐

