Django 4重写save()方法时查询未实时更新问题求助
Django 4重写save()方法时,多对多字段查询不实时更新的解决办法
为啥会出现这个问题?
Django为了减少数据库查询次数,会给模型实例的多对多关系查询结果做缓存。你第一次调用self.exercises.all()时,结果就存在实例的缓存里了,后面再调用all()直接取缓存的旧数据,不会重新去数据库查新的——哪怕父类的save方法已经修改了关联的练习数据。
怎么解决?
方法1:刷新实例缓存
在父类save之后,调用self.refresh_from_db(),强制从数据库重新加载整个实例的数据,包括多对多关联:
class Routine(models.Model): exercises = models.ManyToManyField(Exercise) def save(self, *args, **kwargs): e = self.exercises.all() # 返回初始的3个练习 super().save(*args, **kwargs) # 父类方法修改关联练习 self.refresh_from_db() # 清空缓存,从数据库重新拉数据 e = self.exercises.all() # 现在拿到的就是更新后的练习列表
方法2:直接从数据库查最新数据
如果不想刷新整个实例,也可以绕过实例的缓存,直接通过模型管理器查询当前实例的最新关联数据:
class Routine(models.Model): exercises = models.ManyToManyField(Exercise) def save(self, *args, **kwargs): e = self.exercises.all() # 返回初始的3个练习 super().save(*args, **kwargs) # 父类方法修改关联练习 # 直接查数据库里当前实例的最新关联 e = Routine.objects.get(pk=self.pk).exercises.all()
额外提醒
多对多的缓存是Django的性能优化手段,大部分时候能减少重复查询,但遇到这种需要在同一方法内获取更新后数据的场景,就得手动处理缓存问题。refresh_from_db()是通用解法,适合大多数情况,操作起来也简单。
内容的提问来源于stack exchange,提问作者Gonzalo Dambra
相关产品推荐
相关产品推荐

