3

Django笔记十二之defer、only指定返回字段 - XHunter

 1 year ago
source link: https://www.cnblogs.com/hunterxiong/p/17274387.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

本篇笔记为Django笔记系列之十二,首发于公号【Django笔记】

本篇笔记将介绍查询中的 defer 和 only 两个函数的用法,笔记目录如下:

  1. defer

1、defer

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'}
"""

2、only

与 defer() 方法的作用相反,only() 的意思是只获取指定的字段,比如:

Entry.objects.only("headline", "rating")

与之对应的 SQL 是:

SELECT `blog_entry`.`id`, `blog_entry`.`headline`, `blog_entry`.`rating` FROM `blog_entry`

同样的,如果访问没有指定的字段,系统会再次查询数据库。

如果是多个 only 连用,那么系统只有最后一个 only 的字段会生效:

Entry.objects.only("headline", "rating").only("body_text")  # 只会获取 body_text 字段数据

作用效果跟 order_by() 一样,后面的参数会覆盖前面的。

defer 和 only 连用

我们可以尝试一下 defer 和 only 的先后顺序,字段是否相同,前者的字段覆盖后者,以及后者的字段覆盖前者等情况,这里不做展开了。

因为,一般人谁会把这个两个函数一起用呢。。。。。。

以上就是本篇笔记所有内容,下一篇笔记将介绍 get_or_create,update_or_create 等方法。

本文首发于本人微信公众号:Django笔记。

原文链接:Django笔记十二之defer、only指定返回字段

如果想获取更多相关文章,可扫码关注阅读:

image

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK