zoukankan      html  css  js  c++  java
  • 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'
    
  • 相关阅读:
    最大子序列和问题的几种算法
    给Repeater控件里添加序号的5种方法
    关于上传(上传所用到的upload和upload的应用)
    .net中的动态时钟 (年月日 时分秒)
    网页总结
    PHP算法将数字金额转换成大写金额
    Linux下编译安装redis,详细教程
    如何让PHP支持Redis
    网络互连技术——第一章随记
    网络互连技术——第二章考试需知
  • 原文地址:https://www.cnblogs.com/wangbaojun/p/13841886.html
Copyright © 2011-2022 走看看