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:序列化保存对象后修改状态
技术正确性
技术上可行,但存在细节问题:
- 两次调用
save(),但通过@transaction.atomic包裹,保证了操作的原子性,不会出现中间状态。 - 原代码返回的
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的最佳实践:
- 跳过了DRF的参数验证机制,如果请求包含参数,无法确保合法性。
- 返回字符串而非标准JSON结构,不符合REST接口的响应规范。
- 原代码缺少
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
相关产品推荐
相关产品推荐

