eagleye

PUT请求与PATCH请求的核心差异及DRF实现指南

一、PUT请求:完整资源替换

定义PUT用于整体更新或创建资源,需提供资源的完整字段(即使未修改的字段也需包含),若资源不存在则可能创建新资源。

关键特性

  • 幂等性:多次执行相同PUT请求结果一致(最终状态由最后一次请求决定)。
  • 数据完整性:必须包含资源的所有必填字段,未提供的字段可能被重置为默认值或清空。

DRF实现示例(含文件上传):

# views.py(视图集处理PUT请求)

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

instance = self.get_object()

# 需传递完整用户信息(含文件字段avatar)

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

serializer.is_valid(raise_exception=True) # 触发序列化器验证

serializer.save() # 调用序列化器update方法

return Response(serializer.data)

二、PATCH请求:部分资源更新

定义PATCH用于增量更新资源,仅需提供待修改的字段,未提及的字段保持原有值。

关键特性

  • 非强制幂等性:若更新逻辑为“增加库存10”,重复调用会导致库存持续增加(需通过业务逻辑保证幂等性)。
  • 数据局部性:仅传递变化的字段,减少网络传输量。

DRF实现示例

# views.py(视图集处理PATCH请求)

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

instance = self.get_object()

# 仅传递需修改的字段(如仅更新avatar或username)

serializer = self.get_serializer(instance, data=request.data, partial=True) # partial=True允许部分更新

serializer.is_valid(raise_exception=True)

serializer.save()

return Response(serializer.data)

三、核心差异对比

维度

PUT请求

PATCH请求

更新范围

完整覆盖资源

仅修改指定字段

请求体要求

必须包含所有必填字段

仅包含待修改字段

幂等性

天然幂等(多次执行结果一致)

需业务逻辑保证幂等性

适用场景

全量替换(如用户信息重置)

局部修改(如更新头像、邮箱)

四、DRF文件上传的企业级实现(PUT/PATCH通用)

1. 前端请求格式(Axios示例)

// 必须使用FormData传递文件+普通字段

const formData = new FormData();

formData.append('avatar', file); // 文件字段(二进制流)

formData.append('username', 'new_username'); // 普通字段

axios.patch('/api/users/1/', formData, {

headers: {'Content-Type': 'multipart/form-data'}

});

2. 后端核心配置

# settings.py

REST_FRAMEWORK = {

'DEFAULT_PARSER_CLASSES': [

'rest_framework.parsers.MultiPartParser', # 解析文件

'rest_framework.parsers.JSONParser', # 解析JSON

]

}

3. 序列化器文件验证与处理

# serializers.py

class UserSerializer(serializers.ModelSerializer):

class Meta:

model = User

fields = ['id', 'username', 'avatar']

def validate_avatar(self, value):

# 企业级验证:文件类型+大小限制

if value.size > 5 * 1024 * 1024: # 5MB

raise serializers.ValidationError("文件大小不能超过5MB")

return value

def update(self, instance, validated_data):

# 仅更新传递的字段(支持PUT/PATCH)

for attr, value in validated_data.items():

setattr(instance, attr, value)

instance.save()

return instance

五、企业级最佳实践

1. 优先使用PATCH处理文件上传

o 减少无效字段传输,避免因遗漏字段导致数据丢失。

在视图集默认开启partial=True:def get_serializer(self, *args, **kwargs):

kwargs.setdefault('partial', True) # 全局支持部分更新

return super().get_serializer(*args, **kwargs)

2. 文件存储与安全

使用云存储(如AWS S3、阿里云OSS)替代本地存储:DEFAULT_FILE_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'

限制文件访问权限:生成带过期时间的签名URL(如django-storages自动支持)。

3. 异步处理大文件

Celery异步生成缩略图或扫描病毒:@shared_task

def process_avatar(user_id):

user = User.objects.get(id=user_id)

generate_thumbnail(user.avatar.path) # 生成缩略图

六、常见问题排查

  • 400错误“文件字段缺失”PUT请求未传递完整字段,需补充所有必填项。
  • 415错误“不支持的媒体类型”:未配置MultiPartParser或前端未设置multipart/form-data。
  • 文件验证失败:检查序列化器validate_<field>方法中的类型/大小限制。

通过严格区分PUT/PATCH语义,并结合DRF的序列化器验证与文件处理机制,可构建安全、高效的企业级API。

 

posted on 2025-07-23 10:49  GoGrid  阅读(6)  评论(0)    收藏  举报

导航