You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

DRF嵌套路由场景下无法捕获Photo.DoesNotExist异常问题求助

问题根因

  1. 序列化器的create方法预期返回值为创建完成的模型实例,你在异常分支返回的Response对象会被serializer.save()当作模型实例传递到后续逻辑,无法触发正确的响应构造。
  2. 你重写的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 06:39:04