Django ORM Queryset 的緩存機制, 惰性查詢簡述


在Django的ORM中 必須注意由於QuerySet的 cache導致的數據獲取不正確的問題

在哪些情況下不會出發QuerySet緩存?
隱式存儲QuerySet(查詢語句沒有顯示賦值給變量而直接進行遍歷或截取)

>>> from project.models import ProjectModel
>>> 
>>> print([project_instance.name for project_instance in ProjectModel.objects.all()])
['first-test', 'test百度', 'project002']
>>> ProjectModel.objects.filter(name="project002").update(name="project003")
1
>>> print([project_instance.name for project_instance in ProjectModel.objects.all()])
['first-test', 'test百度', 'project003']

而顯示的存儲QuerSet 並且經過完整遍歷才會觸發緩存

完整遍歷的情況

>>> projects_queryset = ProjectModel.objects.all()
>>> print([project_instance for project_instance in projects_queryset])        # 完整遍歷
[<ProjectModel: first-test>, <ProjectModel: test百度>, <ProjectModel: project007>]
>>> ProjectModel.objects.filter(name="project007").update(name="project008")
1
>>> projects_queryset[1:3]
[<ProjectModel: test百度>, <ProjectModel: project007>]  # project007還是緩存的老數據

不遍歷的情況

>>> projects_queryset = ProjectModel.objects.all()
>>> projects_queryset
<QuerySet [<ProjectModel: first-test>, <ProjectModel: test百度>, <ProjectModel: project008>]>
>>> ProjectModel.objects.filter(name="project008").update(name="project009")
1
>>> projects_queryset[1:3]
<QuerySet [<ProjectModel: test百度>, <ProjectModel: project009>]>  # 沒拿緩存 project009

還有一種場景 也是需要注意的:
獲取到單個QuerySet對象后 通過objects update方法修改了部分字段值,此時的QuerySet還是緩存數據

>>> projects_obj = ProjectModel.objects.filter(name="project0011").first()
>>> projects_obj.name
'project0011'
>>> ProjectModel.objects.filter(name="project0011").update(name="project0012")
1
>>> projects_obj.name
'project0011'

有兩種方法可以解決這個問題

  1. 使用save修改
>>> projects_obj = ProjectModel.objects.filter(name="project0012").first()
>>> projects_obj.name
'project0012'
>>> projects_obj.name = "project0013"
>>> projects_obj.save()
>>> projects_obj.name
'project0013'
  1. 使用refresh_from_db()
>>> projects_obj = ProjectModel.objects.filter(name="project0013").first()
>>> projects_obj.name
'project0013'
>>> ProjectModel.objects.filter(name="project0013").update(name="project0014")
1
>>> projects_obj.refresh_from_db()
>>> projects_obj.name
'project0014'


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM