- django ORM中model对应的数据表,对model对象进行操作后,会返回queryset对象。queryset对象并不只是查询数据库得到的数据集合。正确理解queryset对象的特性,可以减少一些没必要的数据库IO,提高数据库的访问效率。
- 在了解特性前,需要了解几个问题。
- 哪些django ORM操作会操作数据库,哪些不会?
- 怎么查看最终转换成什么sql语句?执行的情况如何?
- 如下示例,通过connection.queries查看当前数据库连接执行的sql语句和执行时间:
- connection.queries必须在Debug=True时使用
>> from django.db import connection
>> connection.queries
[]
>> from project.models import FvrProject
>> FvrProject.objects.first()
<FvrProject: project 1>
>> connection.queries
[{'sql': b'SELECT @@SQL_AUTO_IS_NULL', 'time': '0.049'}, {'sql': b'SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED', 'time': '0.040'}, {'sql': ...]
惰性执行
- 创建一个queryset对象,不会马上执行数据库操作,这就是queryset的惰性执行特性。
- 如下示例all、filter方法,都会产生queryset对象,但实际上并没有执行数据库操作:
>> from django.db import connection
>> from project.models import FvrProject
>>> len(connection.queries)
4
>>> q=FvrProject.objects.all()
>>> len(connection.queries)
4
>>> q=q.filter(is_active=True)
>>> len(connection.queries)
4
>>> q=q.filter(is_active=True)
>>> q=q.filter(id__lt=100)
>>> len(connection.queries)
4
缓存
- 每个QuerySet包含一个缓存空间。理解它是如何工作的将帮助你编写最有效的代码。
- 在新创建的QuerySet中,缓存是空的。第一次对QuerySet求值时,Django会将查询结果保存在QuerySet的缓存中,并返回显式请求的结果(例如,如果QuerySet被遍历,则返回下一个元素)。QuerySet的后续计算重用缓存的结果。
- 请记住这种缓存行为,因为如果你没有正确使用QuerySets,会产生意向不到的结果。
- 如示例1的两个print操作进行了两次数据库查询,如果获取数据是一致的,则应该采用示例2。当然如果示例2中两次print操作间隔时间过长,queryset中缓存的数据与数据库最新数据不一致,将可能引发错误。
>>> print([e.headline for e in Entry.objects.all()])
>>> print([e.pub_date for e in Entry.objects.all()])
>>> queryset = Entry.objects.all()
>>> print([p.headline for p in queryset])
>>> print([p.pub_date for p in queryset])