Django之orm
- orm的定义
- 为什么要有orm
- orm的核心在哪
- 什么时候queryset 被 evaluated (个人理解为利用)
- 什么时候queryset会被缓存
- 什么时候缓存被破坏
- F查询和Q查询
- 多表查询会出现什么问题以及如何避免
- orm 是object-related-mapping 的缩写,翻译为对象关系映射------>将我们对编写的model模型操作 和对数据库里面的表字段的操作 相关联----->形成一种映射的关系
- 第二个问题放到后面作 核心在于懒加载(个人认为哈) 那么什么是懒加载:the act of creating a
- doesn’t involve any database activity.(当我们创建queryset时,并没有查询数据库)
- instances = Model.objects.all()------>并没有连接数据库,没对数据库中的表做任何操作(好处就是显而易见的数据库的负荷减少了)
- 文档说明:Internally, a
QuerySet
can be constructed, filtered, sliced, and generally passed around without actually hitting the database----->当queryset被创建,过滤,切片,传递的时候都没有真正的查询数据库
- 那queryset被创建,什么时候才会真正连接操作数据库:当querySet被 使用的时候
- 步长切片
- len(queruset)
- 字符串化queryset
- 列表化queryset:instances = list(queryset)
- *** 遍历queryset
- 从queryset中取值
- 使用queryset无法避免,那么就应该考虑如何减少数据库操作----使用queryset 是能够被缓存的(The first time a
QuerySet
is evaluated – and, hence, a database query happens – Django saves the query results in theQuerySet
’s cache and returns the results that have been explicitly requested (e.g., the next element, if theQuerySet
is being iterated over)):-
#错误示范 >>> 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的缓存被破坏:
- 缓存被破坏的条件: this means that limiting the queryset using an array slice or an index will not populate the cache.(数组切片,和索引取值)
-
>>> queryset = Entry.objects.all() >>> print(queryset[5]) # Queries the database >>> print(queryset[5]) # Queries the database again
-
- 如何避免:在需要的时候,先对queryset进行操作,使他们被缓存,然后在缓存的queryset进行操作
-
>>> queryset = Entry.objects.all() >>> [entry for entry in queryset] # Queries the database >>> print(queryset[5]) # Uses cache >>> print(queryset[5]) # Uses cache
-
- 常见的被缓存的情况:
-
>>> [entry for entry in queryset] >>> bool(queryset) >>> entry in queryset >>> list(queryset)
-
- 所以 在django restframework中 在GenericApiView层次上 内置了 queryset类属性!
- 缓存被破坏的条件: this means that limiting the queryset using an array slice or an index will not populate the cache.(数组切片,和索引取值)
- F查询和Q查询:
- 导入:from django.db.models import F,Q
- F查询:常用来做条件比较 ;*** 在model层次上的操作是直接对数据库表字段的操作(1.避免了竞态条件!!! 2 避免了将模型数据拉倒内存中然后在进行操作)
- Q 查询 :用来做字段查询条件之间的连接符:where ... and(or) ...,起到这种 and(or)作用,但是要注意的是Q查询的时候,关键字字段要在其之后 (Q(),‘look_up’=args)
- 多表查询
- 第一步优化:
- 需要查询两张关联表的时候,正常情况,我们需要查询两次database,第一次找出目标对象,第二次找出目标对象在数据表中关联的对象;
- 这种时候 select_related()字段的 会一次性取回两张表 需要查询多张表的时候,查询4张,这个时候,我们往往查询表的次数会高于4次,因为有一些表作为枢纽表总是会被重复查询
- 这时候使用prefetch_related:我们只会4次,然后python程序会帮我们关联4张表中我们需要的数据
- 第二步优化:
- 结合使用select_related 和prefetch_related 字段 还能减少查询次数!
- 有兴趣研究的 https://www.cnblogs.com/evilliu/articles/6109640.html
- 需要查询两张关联表的时候,正常情况,我们需要查询两次database,第一次找出目标对象,第二次找出目标对象在数据表中关联的对象;
- 为什么有orm
- 便捷性:将select语句封装为函数操作,更优雅,更简单
- 从懒加载和缓存的层次:对于内存利用更为合适