基于Django Rest Framework的模型数据更新实现咨询
嘿,我帮你看看这段DRF的update代码,这里确实有几个关键问题,咱们一步步捋清楚:
现有代码的核心问题
- 根本不是更新操作,而是新建数据:你初始化
InfoSerializer时只传了data=data,没有传入要更新的instance实例。DRF序列化器的规则是:不带instance时,save()会执行create()方法创建新对象;只有传入目标instance,才会执行update()方法修改现有数据。所以你现在的代码每次调用更新接口都会新增一条Info记录,完全达不到更新现有数据的目的。 - 浪费了ModelViewSet的内置逻辑:父类
ModelViewSet已经帮你实现了获取目标实例、权限校验、处理部分更新(PATCH请求)等逻辑,你重写后完全绕开了这些成熟的实现,反而要自己处理很多边缘情况(比如实例不存在的404异常)。 - 返回格式不符合DRF规范:你用了原生的
JsonResponse,但DRF提供的Response类能自动处理内容协商(比如根据请求头返回不同格式)、正确设置状态码,比原生响应更适配框架生态。 - 冗余配置:
lookup_field = 'id'是DRF的默认值,完全可以省略不写,不会影响功能。
优化后的实现方案
分两种情况来处理,根据你的需求选择:
情况1:无特殊自定义需求(推荐)
如果只是需要标准的更新逻辑,完全不需要重写update方法,ModelViewSet已经内置了完整的CRUD操作,直接用默认实现即可:
class InfoViews(viewsets.ModelViewSet): queryset = Info.objects.all() serializer_class = InfoSerializer # lookup_field = 'id' # 可省略,默认就是id
情况2:需要自定义更新逻辑(比如更新前后加额外操作)
如果要在更新前后加自定义逻辑(比如记录操作日志、修改关联字段),正确的重写方式应该复用父类的核心逻辑:
from rest_framework.response import Response class InfoViews(viewsets.ModelViewSet): queryset = Info.objects.all() serializer_class = InfoSerializer def update(self, request, *args, **kwargs): # 1. 利用父类方法获取要更新的目标实例(自动处理404异常) instance = self.get_object() # 2. 初始化序列化器:传入instance+data,同时支持部分更新(兼容PATCH请求) serializer = self.get_serializer( instance, data=request.data, partial=kwargs.get('partial', False) ) serializer.is_valid(raise_exception=True) # --- 这里加你的自定义逻辑,比如更新前校验或日志记录 --- # example: record_update_log(instance, request.user) # 3. 执行更新(复用父类的perform_update,兼容信号等钩子) self.perform_update(serializer) # --- 这里加更新后的自定义逻辑 --- # example: sync_related_data(instance) return Response(serializer.data)
额外注意点
确保你的InfoSerializer是正确的ModelSerializer实现,比如:
from rest_framework import serializers from .models import Info class InfoSerializer(serializers.ModelSerializer): class Meta: model = Info fields = '__all__' # 或指定需要序列化的字段
如果需要自定义字段更新逻辑,再在InfoSerializer里重写update方法即可,不用在视图层处理。
内容的提问来源于stack exchange,提问作者user9341676
相关产品推荐
相关产品推荐

