eagleye

DRFPUT请求执行链路解析

一、PUT请求的完整执行流程

1. 前端请求触发视图集的update方法

Axios发送的PUT请求会被DRF路由系统匹配到ModelViewSet的update动作(对应HTTP PUT方法),执行UpdateModelMixin中的update方法。

2. 序列化器验证(is_valid)优先于perform_update

# DRF UpdateModelMixin.update() 核心代码

def update(self, request, *args, **kwargs):

partial = kwargs.pop('partial', False)

instance = self.get_object() # 获取待更新对象

# 创建序列化器实例(传入待更新对象和请求数据)

serializer = self.get_serializer(instance, data=request.data, partial=partial)

serializer.is_valid(raise_exception=True) # 【第一步:验证数据】

self.perform_update(serializer) # 【第二步:执行更新】

return Response(serializer.data)

3. perform_update调用序列化器的save方法

# DRF UpdateModelMixin.perform_update()

def perform_update(self, serializer):

serializer.save() # 【第三步:触发序列化器的update方法】

4. 序列化器的save方法调用update

当序列化器传入instance(待更新对象)时,save()会自动调用update方法:

# DRF Serializer.save() 逻辑

def save(self, **kwargs):

if self.instance is not None: # PUT请求会传入instance

self.instance = self.update(self.instance, self.validated_data) # 【第四步:执行更新逻辑】

return self.instance

二、您描述中的关键偏差修正

错误认知

正确流程

原因

"首先触发perform_update"

先执行is_valid,再触发perform_update

perform_update是在数据验证通过后才调用的钩子方法,目的是允许开发者重写更新逻辑(如添加日志、权限检查)。

"serializer.save()触发is_valid"

is_valid必须手动调用(或通过raise_exception=True隐式确保)

DRF不会自动调用is_valid,若未验证直接调用save(),会抛出ValidationError。

"save()触发is_valid()"

is_valid()是save()的前置条件

只有is_valid()返回True后,validated_data才会生成,save()才能正常执行update。

三、核心结论:正确执行顺序

graph TD

A[前端PUT请求] --> B[视图集.update()方法]

B --> C[创建序列化器实例]

C --> D[serializer.is_valid() 验证数据]

D --> E[视图集.perform_update(serializer)]

E --> F[serializer.save()]

F --> G[序列化器.update() 执行更新]

G --> H[返回更新后的数据]

四、验证建议

若需确认项目中的实际执行顺序,可在关键节点添加日志:

# 1. 视图集重写update方法

def update(self, request, *args, **kwargs):

print("触发视图集.update()")

return super().update(request, *args, **kwargs)

# 2. 序列化器重写is_valid和update

def is_valid(self, raise_exception=False):

print("触发序列化器.is_valid()")

return super().is_valid(raise_exception=raise_exception)

def update(self, instance, validated_data):

print("触发序列化器.update()")

return super().update(instance, validated_data)

执行PUT请求后,控制台输出顺序应为:

触发视图集.update()

触发序列化器.is_valid()

触发序列化器.update()

总结

DRF的PUT请求处理遵循"验证优先 → 钩子调用 → 保存更新"的逻辑,核心是is_valid()必须在save()之前执行。您的描述中颠倒了is_valid与perform_update的顺序,实际流程中数据验证是更新操作的前置条件。

 

posted on 2025-07-23 09:44  GoGrid  阅读(4)  评论(0)    收藏  举报

导航