DRF序列化器方法字段在update()方法更新关联模型后仍返回旧值
问题原因
该问题是Django ORM的关联实例缓存机制导致的:
- Django会将模型实例的关联查询结果缓存到实例内部,后续访问同一关联时直接读取缓存,不会重新查询数据库。对于
OneToOne反向关联(你的Preference与User的关联关系),缓存会存储在shared_user实例的_<related_name>_cache属性中。 - 你在
update()方法中通过Preference.objects.get_or_create()拿到的是独立的Preference实例,修改并保存后,并未同步刷新shared_user实例上已缓存的旧Preference对象。当get_enforce_mfa()通过obj.shared_user.preference访问时,直接读取了缓存的旧实例,因此返回更新前的False。
解决方案
可根据场景选择以下任意一种方案:
方案1:更新Preference后清除关联缓存
在preference.save()之后添加代码,清除shared_user上的preference缓存,确保后续访问时重新查询数据库:
preference.enforce_mfa = enforce_mfa preference.save() # 清除shared_user实例上的preference缓存 if hasattr(instance.shared_user, '_preference_cache'): del instance.shared_user._preference_cache
也可以直接调用refresh_from_db()刷新整个shared_user实例,自动清除所有关联缓存:
preference.enforce_mfa = enforce_mfa preference.save() instance.shared_user.refresh_from_db()
方案2:get_enforce_mfa直接查询最新值
修改get_enforce_mfa方法,直接从数据库查询Preference的最新值,绕过实例关联缓存:
def get_enforce_mfa(self, obj): try: # 直接查询数据库,不读取实例缓存 return Preference.objects.get(user=obj.shared_user).enforce_mfa except ObjectDoesNotExist: return False
方案3:通过关联属性修改Preference
修改update中的更新逻辑,通过shared_user的反向关联获取/创建Preference实例,确保修改的是缓存中的同一个实例:
if self.context['request'].data.get('enforce_mfa'): enforce_mfa = json.loads(str(self.context['request'].data.get('enforce_mfa')).lower()) # 直接通过shared_user的反向关联获取/创建Preference try: preference = instance.shared_user.preference except ObjectDoesNotExist: preference = Preference(user=instance.shared_user) preference.enforce_mfa = enforce_mfa preference.save()
额外优化建议:
Meta中设置的depth=1会自动递归序列化所有嵌套关联字段,若不需要深层嵌套的默认序列化,可移除该参数,减少不必要的数据库查询开销。
内容的提问来源于stack exchange,提问作者Anuj TBE
相关产品推荐
相关产品推荐

