Django之orm

  • orm的定义
  • 为什么要有orm
  • orm的核心在哪
  • 什么时候queryset 被 evaluated (个人理解为利用)
  • 什么时候queryset会被缓存
  • 什么时候缓存被破坏
  • F查询和Q查询
  • 多表查询会出现什么问题以及如何避免

 

      1.  orm 是object-related-mapping 的缩写,翻译为对象关系映射------>将我们对编写的model模型操作 和对数据库里面的表字段的操作 相关联----->形成一种映射的关系
      2. 第二个问题放到后面作
      3. 核心在于懒加载(个人认为哈) 那么什么是懒加载:the act of creating a 

QuerySet

      doesn’t involve any database activity.(当我们创建queryset时,并没有查询数据库)
  1.   instances = Model.objects.all()------>并没有连接数据库,没对数据库中的表做任何操作(好处就是显而易见的数据库的负荷减少了)
  2. 文档说明:Internally, a QuerySet can be constructed, filtered, sliced, and generally passed around without actually hitting the database----->当queryset被创建,过滤,切片,传递的时候都没有真正的查询数据库

  • 那queryset被创建,什么时候才会真正连接操作数据库:当querySet被 使用的时候
    1.   步长切片
    2.        len(queruset)
    3.        字符串化queryset 
    4.         列表化queryset:instances = list(queryset)
    5.      ***  遍历queryset
    6.      从queryset中取值
  •  使用queryset无法避免,那么就应该考虑如何减少数据库操作----使用queryset 是能够被缓存的(The first time a QuerySet is evaluated – and, hence, a database query happens – Django saves the query results in the QuerySet’s cache and returns the results that have been explicitly requested (e.g., the next element, if the QuerySet is being iterated over)):
    1.   
      #错误示范
      
      
      >>> print([e.headline for e in Entry.objects.all()])
      >>> print([e.pub_date for e in Entry.objects.all()])
      #这样就会进行两次迭代 两次hitting database

       

      #正确演绎
      >>> queryset = Entry.objects.all() >>> print([p.headline for p in queryset]) # Evaluate the query set. >>> print([p.pub_date for p in queryset]) # Re-use the cache from the evaluation.

       

        
  • 那么如何避免queryset的缓存被破坏:
    1.   缓存被破坏的条件: this means that limiting the queryset using an array slice or an index will not populate the cache.(数组切片,和索引取值)
      1.   
        >>> queryset = Entry.objects.all()
        >>> print(queryset[5]) # Queries the database
        >>> print(queryset[5]) # Queries the database again

         

    2. 如何避免:在需要的时候,先对queryset进行操作,使他们被缓存,然后在缓存的queryset进行操作
      1.   
        >>> queryset = Entry.objects.all()
        >>> [entry for entry in queryset] # Queries the database
        >>> print(queryset[5]) # Uses cache
        >>> print(queryset[5]) # Uses cache
    3.   常见的被缓存的情况:
      1.   
        >>> [entry for entry in queryset]
        >>> bool(queryset)
        >>> entry in queryset
        >>> list(queryset)
    4.   所以 在django restframework中 在GenericApiView层次上 内置了 queryset类属性!
  • F查询和Q查询:
    1.   导入:from django.db.models import F,Q
    2.       F查询:常用来做条件比较   ;*** 在model层次上的操作是直接对数据库表字段的操作(1.避免了竞态条件!!! 2 避免了将模型数据拉倒内存中然后在进行操作)
    3.       Q 查询 :用来做字段查询条件之间的连接符:where ... and(or) ...,起到这种 and(or)作用,但是要注意的是Q查询的时候,关键字字段要在其之后  (Q(),‘look_up’=args)  
  • 多表查询
    1. 第一步优化:
      1. 需要查询两张关联表的时候,正常情况,我们需要查询两次database,第一次找出目标对象,第二次找出目标对象在数据表中关联的对象;
        1.   这种时候 select_related()字段的 会一次性取回两张表
        2. 需要查询多张表的时候,查询4张,这个时候,我们往往查询表的次数会高于4次,因为有一些表作为枢纽表总是会被重复查询
        3.     这时候使用prefetch_related:我们只会4次,然后python程序会帮我们关联4张表中我们需要的数据
      2. 第二步优化:
        1.   结合使用select_related 和prefetch_related 字段 还能减少查询次数!
        2.   有兴趣研究的  https://www.cnblogs.com/evilliu/articles/6109640.html
  • 为什么有orm
    1.   便捷性:将select语句封装为函数操作,更优雅,更简单
    2.     从懒加载和缓存的层次:对于内存利用更为合适

posted @ 2020-06-10 14:18  ZMZ沐梓  阅读(171)  评论(0编辑  收藏  举报