新代系统使用期限密码▉▉▉【一电一 17154833762-】▉▉defer 的英语单词的意思是 延迟、推迟,我们可以通过将字段作为参数传入,可以达到在获取数据的时候指定不获取该字段数据,常用于一些 textfield 字段上。
假设我们有一个 TestModel,有一个字段名为 text_field,字段类型为 textfield,里面存了大量字符串数据.
那么如果我们再获取这个 model 数据的时候,只想要这个 model 的其他字段信息, text_field 字段的内容我们在这一次用不上,那么我们就可以通过 defer() 方法来指定不获取该字段内容。
由于对于这一类大容量数据,系统在从数据库中 fetch 数据的时候会花费大量时间,而这部分不必要的时间我们是可以避免的。
TestModel.objects.defer("text_field")
上面的语句将 text_field 这个字段名作为参数传入 defer() 函数,系统返回数据的时候将不会返回他的字段。
我们以 Blog 这个model为例对这个函数进行测试,我们获取 Blog 的数据,但是指定不获取 name 这个字段的数据:
Blog.objects.defer("name")
我们可以打印一下这条命令执行的 SQL 语句:
Blog.objects.defer("name").query.__str__()
SELECT `blog_blog`.`id`, `blog_blog`.`tagline` FROM `blog_blog`
可以看到转化的 SQL 语句没有把我们指定的 name 字段返回。
不获取外键关联的某些字段
如果我们通过 select_related 关联了外键数据,也可以指定不获取外键的某些字段,列如:
Entry.objects.select_related("blog").defer("blog__name")
这样,在获取关联的 blog 的数据的时候,就不会获取 blog 的 name 字段数据。
defer 多字段
Entry.objects.defer('headline', 'body_text')
主键字段不能defer
有一些字段我们是 defer 也不会生效的,列如 model 的主键字段 id。
Blog.objects.defer("id")
上面的操作,系统不会报错,但是也不会生效。
关联外键数据,外键数据不应该被 defer
假设我们通过 Entry 来关联获取 Blog 数据,那么,关联的外键字段 blog_id,则不应该被 defer(),否则会报错。
# 下面的写法会报错
Entry.objects.select_related("blog").defer("blog_id")
访问被 defer 的字段
假设我们在获取 Blog 数据的时候,defer 了 name 字段,那么我们还可以访问 name 字段吗?
答案是可以的,不过由于我们在第一步的时候没有获取该字段,所以访问该字段的时候,系统会再次请求一遍数据库。
blog = Blog.objects.defer("name").first()
"""
这个时候打印出 blog 的所有字段是:
blog.__dict__
{'_state': <django.db.models.base.ModelState object at 0x7fb2de420668>, 'id': 1, 'tagline': 'asd'}
"""
print(blog.name) # 访问被 defer 的字段,系统会再次请求数据库
"""
这个时候再次打印出 blog.__dict__ 内容是:
{'_state': <django.db.models.base.ModelState object at 0x7fb2de420668>, 'id': 1, 'tagline': 'asd', 'name': 'hunter'}
"""


















暂无评论内容