DRF UpdateModelMixin未调用自定义Manager的update方法,返回旧数据如何解决?
解决DRF UpdateModelMixin不调用自定义Manager及返回旧数据问题
问题分析
- DRF的
UpdateModelMixin默认流程是:获取数据库实例→通过序列化器验证数据→调用serializer.save()→触发序列化器的update方法。这个update方法默认直接修改内存中实例的属性,再调用instance.save(),不会触发Manager的批量update()方法(Manager的update()是直接操作数据库的批量更新,不经过实例的save方法)。 - 你重写
perform_update时用了HelloModel.objects.update(**serializer.validated_data),这会直接更新数据库,但视图中持有的还是更新前的内存实例,所以返回的是旧数据。
最优解决方案
方案一:在Model层统一处理时间字段(推荐)
把date_created和last_modified的设置逻辑放在Model的save方法中,不管是创建还是更新操作,只要调用save()就会自动处理,完全适配DRF的默认流程:
# models.py from django.db import models from django.utils import timezone class HelloModel(models.Model): # 你的业务字段示例 name = models.CharField(max_length=100) date_created = models.DateTimeField(null=False) last_modified = models.DateTimeField(null=False) def save(self, *args, **kwargs): if not self.pk: # 首次创建时设置date_created self.date_created = timezone.now() self.last_modified = timezone.now() # 每次保存都更新last_modified super().save(*args, **kwargs)
无需修改DRF的视图或序列化器,create和update操作都会自动维护时间字段,逻辑最简洁且通用。
方案二:重写Serializer的update方法(需保留Manager逻辑时用)
如果必须依赖自定义HelloManager的更新逻辑,在序列化器中重写update方法,确保更新后刷新实例:
# serializers.py from rest_framework import serializers from .models import HelloModel class HelloWriteSerializer(serializers.ModelSerializer): class Meta: model = HelloModel fields = '__all__' def update(self, instance, validated_data): # 调用自定义Manager的更新逻辑(示例为过滤单实例后更新) HelloModel.objects.filter(pk=instance.pk).update(**validated_data) # 从数据库刷新实例,获取最新数据 instance.refresh_from_db() return instance
此时视图无需重写perform_update,DRF的默认流程会调用这个update方法,返回的就是更新后的数据。
方案三:正确重写perform_update方法
如果一定要在视图层处理,需确保更新后刷新实例:
# views.py def perform_update(self, serializer): # 用序列化器的默认save方法更新实例 instance = serializer.save() # 若需调用Manager的自定义逻辑,可在此执行 # HelloModel.objects.filter(pk=instance.pk).update(...) # 刷新实例确保返回最新数据 instance.refresh_from_db() serializer.instance = instance
内容的提问来源于stack exchange,提问作者Angelo Orate
相关产品推荐
相关产品推荐

