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

DRF中对实例执行额外操作的几种写法:哪种更规范实用?

文档状态修改的四种实现方案分析

以下针对四种修改文档状态的实现方案,逐一分析技术正确性及实践场景:

方案1:向标准模型序列化器传入自定义数据

技术正确性

技术上完全正确。通过partial=True允许部分更新,手动传入{'status': 'E'}作为更新数据,经过序列化器的验证逻辑后保存,符合DRF的核心流程。只要'E'符合序列化器中status字段的验证规则(比如枚举值约束),就能正常执行。

实践建议

  • 优点:借助序列化器的验证机制,确保状态值符合业务规则,避免非法数据写入数据库。
  • 缺点:硬编码状态值,灵活性不足,仅适用于固定状态切换的场景(比如统一将状态改为"已编辑")。
class PZSaveAPIView(APIView):
    @transaction.atomic
    def patch(self, request, pk, format=None):
        document = get_object_or_404(PZ, pk=pk)
        print(request.data)
        serializer = PZModelSerializer(
            document, data={'status': 'E'}, partial=True)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

方案2:序列化保存对象后修改状态

技术正确性

技术上可行,但存在细节问题:

  1. 两次调用save(),但通过@transaction.atomic包裹,保证了操作的原子性,不会出现中间状态。
  2. 原代码返回的serializer.data是第一次保存的数据,未包含后续修改的status值,会导致响应数据与实际数据库状态不一致。

实践建议

  • 适用场景:需要先处理请求中的其他参数,再强制修改状态的场景。
  • 优化点:修改状态后,建议重新序列化对象再返回,确保响应数据准确。
class PZSaveAPIView(APIView):
    @transaction.atomic
    def patch(self, request, pk, format=None):
        document = get_object_or_404(PZ, pk=pk)
        serializer = PZModelSerializer(
            document, data=request.data, partial=True)
        if serializer.is_valid():
            pz = serializer.save()
            pz.status = 'S'
            pz.save()
            return Response(PZModelSerializer(pz).data)  # 优化:返回最新数据

        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

方案3:将逻辑封装在序列化器的update方法中

技术正确性

这是DRF推荐的分层实现方式,技术上完全正确。将状态修改逻辑封装在序列化器的update方法中,视图仅负责处理请求分发,符合单一职责原则。

实践建议

  • 注意事项:当前代码直接将status设为'S',会忽略validated_data中的status值。如果业务需要保留请求传入的状态,需调整为instance.status = validated_data.get('status', 'S')。
  • 优点:视图逻辑简洁,业务规则集中在序列化器,便于复用和维护,适合状态修改是固定业务规则的场景。
class PZUpdateSerializer(serializers.ModelSerializer):
    class Meta:
        model = PZ
        fields = '__all__'
        
    def update(self, instance, validated_data):
        instance.status = 'S'  # 若需支持请求传入状态,改为validated_data.get('status', 'S')
        instance.save()
        return instance

方案4:不使用序列化器

技术正确性

代码本身能运行,但不符合REST API的最佳实践:

  1. 跳过了DRF的参数验证机制,如果请求包含参数,无法确保合法性。
  2. 返回字符串而非标准JSON结构,不符合REST接口的响应规范。
  3. 原代码缺少request参数,且未处理数据库操作可能出现的异常(比如字段约束冲突),缺乏错误处理机制。

实践建议

  • 仅适用于极简场景(比如无参数的状态切换接口),不推荐在正式项目中使用。
  • 若坚持这种写法,建议补充异常捕获,并返回标准JSON响应。
class PZSaveAPIView(APIView):
    def patch(self, request, pk):  # 修复:补充request参数
        try:
            document = get_object_or_404(PZ, pk=pk)
            document.set_status_saved()
            document.save()
            return Response({'message': 'Document saved'}, status=status.HTTP_200_OK)
        except Exception as e:
            return Response({'error': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

内容的提问来源于stack exchange,提问作者skelaw

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 22:30:51