Django小技巧16: 数据库访问优化 Posted November 05, 2018 ?...访问外键值 如果你只需外键的ID Python Do post.author_id Python Don't post.author.id 如果你的博文中有一个 author 的外键,Django 会自动将主键存储在属性...如果你如果使用author来访问 ID, 数据则会多出一个额外的查询,就会产生开销。...如果你只想知道 QuerySets 是否为空....减少不必要的查询次数 就是之前讲过的 select_related Python Do review = Review.objects.select_related('author').first()
db:如果现在执行,则返回使用的数据库。 三、返回新QuerySets的API 以下的方法都将返回一个新的QuerySets。重点是加粗的几个API,其它的使用场景很少。...例如: >>> qs1.difference(qs2, qs3) 16. select_related() select_related(*fields) 沿着外键关系查询关联的对象的数据...这会生成一个复杂的查询并引起性能的损耗,但是在以后使用外键关系时将不需要再次数据库查询。 下面的例子解释了普通查询和select_related()查询的区别。...('blog').filter(pub_date__gt=timezone.now()) 可以沿着外键查询。...的ForeignKey使用SQL约束ON DELETE CASCADE,任何具有指向要删除的对象的外键的对象将与它们一起被删除。
()类似,针对many-to-many 不要获取你不需要的数据 使用 QuerySet.values() 和 values_list() 当只需要一个字段的值,返回list或者dict时,使用 values...,不要使用 if querysets 。...__nonzero__() ,在数据库层面执行 user.emails.all() ,然后返回结果,放入缓存。 {{ emails|length }} 的使用将调用 QuerySet....QuerySet.delete() 批量操作不会调用类中定义的 save() 或 delete() 方法 直接使用外键的值 获取频道ID: news.channel_id 而不是: news.channel.id...批量插入 用 django.db.models.query.QuerySet.bulk_create() 批量创建对象,减少SQL查询的 数量。
,通过自定义model的instance可以获取外键实体等,它的方法都是记录级方法(都是实例方法,貌似无类方法),不要在里面定义类方法,比如计算记录的总数,查看所有记录,这些应该放在自定义的manager...Q查询混和使用,但不建议这样做,因为混和查询时Q对象要放前面,这样就有难免忘记顺序而出错,所以如果使用Q对象,那就全部用Q对象。...Q对象也很简单,就是把原来filter中的各个条件分别放在一个Q()即可,不过我们还可以使用或与非,分别对应符号为”|”和”&”和”~”,而且这些逻辑操作返回的还是一个Q对象,另外,逗号是各组条件的基本连接符...()——对应返回关联记录实体 原型select_related(*filed) 返回QuerySet 它可以指定返回哪些关联表model instance,这里的field跟filter()中的键一样,...(),QuerySet中的元素中的OneToOne关联及外键对应的是都是关联表的一条记录,如my_entry=Entry.objects.get(id=1),my_entry.blog就是关联表的一条记录的对象
目录 Making queries 进行查询 创建一个对象(一条数据记录) 保存修改的表对象 保存外键字段或多对多字段(ForeignKey or ManyToManyField fields) Retrieving...保存外键字段或多对多字段(ForeignKey or ManyToManyField fields) 外键字段 ForeignKey 更新一个外键字段的写法和普通字段的完全一致,只需要将正确类型的对象分配给相关字段即可...(对象赋值给字段) entry.save() # 调用 .save() 方法 ManyToManyField 想要保存多对多字段,写法和外键字段有点小区别,使用 .add() 方法来记录一个关系。...),返回 True,如果没有结果,返回 False Caching and QuerySets 缓存 和 QuerySets 每一个 QuerySet 都包含一个缓存,来最小化数据库访问次数,知道它的工作原理可以让你写出更高效的代码...--> 推测是 遍历、取值,翻译成取值好像更合适一点) alias 别名 特别点 保存外键字段那里,可以直接给外键对象赋值一个对象(blog 对象 --> blog 属性) cache
select_related方法 select_related将会根据外键关系(注意: 仅限单对单和单对多关系),在执行查询语句的时候通过创建一条包含SQL inner join操作的SELECT语句来一次性获得主对象及相关对象的信息...(‘author__name’).get(id=13) # 使用select_related()可返回所有相关主键信息。...Django提供了prefect_related方法来解决这个问题。prefect_related可用于多对多关系字段,也可用于反向外键关系(related_name)。...,请一定记住使用select_related和prefetch_related一次性获取所有对象信息,从而提升数据库查询效率,避免重复查询。...对与单对单或单对多外键ForeignKey字段,使用select_related方法 对于多对多字段和反向外键关系,使用prefetch_related方法 两种方法均支持双下划线指定需要查询的关联对象的字段名
理解查询集 理解查询集(QuerySets) 是通过简单的代码获取较好性能至关重要的一步。特别是: 理解查询集计算 要避免性能问题,理解以下几点非常重要: QuerySets是延迟的。...使用django.db.connection.queries来了解Django为你编写了什么,以及从这里开始。...如果查询匹配到多于一个对象,它会在数据库中遍历和检索所有这些对象。如果记录中返回了成百上千个对象,代价是非常大的。如果数据库运行在分布式服务器上,网络开销和延迟也是一大因素,代价会是它们的组合。...所以: 使用QuerySet.select_related()和prefetch_related() 充分了解并使用select_related()和prefetch_related(): 在视图的代码中...直接使用外键的值 如果你仅仅需要外键当中的一个值,要使用对象上你已经取得的外键的值,而不是获取整个关联对象再得到它的主键。
values() 返回包含对象具体值的字典的QuerySet values_list() 与values()类似,只是返回的是元组而不是字典。...tags = Tag.objects.only('name').filter(is_delete=False) values() only() 返回的是queryset字典,不是对象,only才是返回的是对象...() 如果我要拿这个模型通过外键绑定的另外一个模型,使用select_related course 模型定义了teacher字段绑定teacher模型 course = Course.objects.only...这样就可以引用模型字段值并使用它们执行数据库操作,而无需实际将它们从数据库中拉出到Python内存中 说白了就是我从数据库拿东西,但是有些需要的字段没有,要通过绑定的外键的app的model拿。...但是名称又是app__字段来命名,这样我要改名称,而且拿第一次的model,放在python内存中,再拿通过外键绑定的另一个model,又要执行第一次步骤,那个效率就不行了,干嘛我不一起拿,所以会用annotate
如果你要执行更复杂的查询(比如,实现筛选条件的 OR 关系),可以使用 Q 对象。 Q 对象(django.db.models.Q)是用来封装一组查询关键字的对象。...在 Django 删除对象时,会模仿 SQL 约束 ON DELETE CASCADE 的行为,换句话说,删除一个对象时也会删除与它相关联的外键对象。...一对多关系 正向 如果一个 model 有一个 ForeignKey字段,我们只要通过使用关联 model 的名称就可以得到相关联的外键对象。...你可以设置和获得外键属性。正如你所期望的,改变外键的行为并不引发数据库操作,直到你调用 save()方法时,才会保存到数据库。...其后根据外键访问时这个实例,就会从缓存中获得它。
简单使用 对于一对一字段(OneToOneField)和外键字段(ForeignKey),可以使用select_related 来对QuerySet进行优化。...select_related 返回一个QuerySet,当执行它的查询时它沿着外键关系查询关联的对象的数据。它会生成一个复杂的查询并引起性能的损耗,但是在以后使用外键关系时将不需要数据库查询。...简单说,在对QuerySet使用select_related()函数后,Django会获取相应外键对应的对象,从而在之后需要的时候不必再查询数据库了。...nid"); 多外键查询 这是针对category的外键查询,如果是另外一个外键呢?...Django >= 1.7,链式调用的select_related相当于使用可变长参数。Django select_related失效,只保留最后一个。
翻译整理自: simpleisbetterthancomplex.com 本文介绍一个非常简单的技巧, 能够帮助你在使用 Django ORM 时优化数据库查询....需要注意的是, Django QuerySets 是惰性查询的, 如果使用得当非常适用。...检索invoices所有对象的一条查询, 和每个invoice供应商的一次查询, 共计101条。...当然, 可以使用select_related方法, 来减轻这种不期望的影响,以便在单次数据查询中,检索所有必要的信息。...推荐一个可以跟踪数据库查询的调试工具Django Debug Toolbar 阅读更多关于Django QuerySet API的文档. Django Documentation
简单使用 对于一对一字段(OneToOneField)和外键字段(ForeignKey),可以使用select_related 来对QuerySet进行优化。...select_related 返回一个QuerySet,当执行它的查询时它沿着外键关系查询关联的对象的数据。它会生成一个复杂的查询并引起性能的损耗,但是在以后使用外键关系时将不需要数据库查询。...简单说,在对QuerySet使用select_related()函数后,Django会获取相应外键对应的对象,从而在之后需要的时候不必再查询数据库了。...nid"); 多外键查询 这是针对category的外键查询,如果是另外一个外键呢?...也接受无参数的调用,Django会尽可能深的递归查询所有的字段。但注意有Django递归的限制和性能的浪费。 Django >= 1.7,链式调用的select_related相当于使用可变长参数。
通过使用 ORM,我们只需要操作 Author 和 Blog 对象,而不用操作相关的数据库表。这里主要介绍一下 Django ORM 的相关使用。...在下图中 orm_blog 通过一个外键和 orm_author 关联。...关联大体上可以分为两种: 只有一个关联实例: 外键关联中包含外键的表、OneToOneField,例如下图中的 orm_blog 只与一个 orm_author 的实例关联 有多个关联实例:外键关联中不含外键的表...`id` ASC LIMIT 1 select_related 会沿着外键递归查询,例如上图中取表 1 的实例时,会沿着外键将表 3 的数据一块取出来。...aggregate: 针对所有记录调用聚合函数,返回一个 dict 对象,下面是使用示例: from django.db.models import Min from django.db.models
() 结果为对象 注意query_set类型的对象 都有该方法。...row.category.name) ③ prefetch_related() 做连表操作依然会影响查询性能,所以出现prefetch_related; prefetch_related:不做连表,多次单表查询外键表...,去重之后显示, 2次单表查询(有几个外键做几次1+N次单表查询) 适用场景:效率高,数据量大的时候适用。...aggregate() 中每一个参数都指定一个包含在字典中的返回值。即在查询集上生成聚合。...from django.db.models import Avg,Sum,Max,Min #求书籍的平均价 ret=models.Book.objects.all().aggregate(Avg('price
仅在需要结果时才执行 SQL)常用过滤器all():返回所有对象filter(**kwargs):返回满足条件的对象exclude(** kwargs):返回不满足条件的对象get(**kwargs):...models.Model): title = models.CharField(max_length=100) publication_date = models.DateField() # 外键关联...models.CASCADE, related_name='books' ) def __str__(self): return self.title正向查询(通过外键属性访问...检测方法Django Debug Toolbar:直观显示请求中的 SQL 查询日志记录:配置日志记录 SQL 语句性能分析工具:如 Django Silk 分析查询性能解决方案方法 1:使用 select_related...,字典的键为字段名,值为字段对应的数据返回一个包含元组的查询集,元组中的元素依次对应指定字段的值 内存占用 相对较高,因为字典需要存储键值对信息 通常更节省内存
如: res = models.Book.objects.all()#只有当我们使用res时才会执行数据库查询的操作 all、only与defer all 拿到自己的所有的属性,但是没有与其他表建立外键的属性...与prefetch_related select_related 括号内只能放一对一、一对多的外键字段,特点:内部自动连表操作,会将括号内外键字段所关联的表与当前表自动拼接成一张表,然后将表中的数据一个一个查询出来封装成一个一个的对象...select_related()括号内放多个外键字段,逗号隔开,会将多个外键字段关联的表与当前表拼成一张大表。...,特点:按步骤查询多张表,然后将查询结果封装到对象中,给用户的感觉好像还是连表操作,括号内支持传多个外键字段,每放一个外键字段就会多走一条SQL语句,多查一张表。...先添加普通的键值 MyFormData.append('username','ylpb'); // 添加了一组普通的简直对,append后面第一个参数是键,第二个参数是值
.取值即可,不会再进行数据库查询 ❝1.如上 select_related 中的参数 hbook 为外键名称,它会将所关联的表中所有信息都查询出来。...2.如果书籍表 BookInfo 中还有外键,我们还想再关联查询那张表的信息,可以用如下的方式:hbook__外键名称,外键和外键之间用双下划线连接。...比如示例中可以改为:select_related(depth=1),它的意思就是往下查询一层。如果书籍表中还有外键,我们都想查询出来,可以:select_related(depth=2),以此类推。...4.示例中的方式是指定查询的外键,只查询了英雄类中所关联的图书。如果英雄类中有好几个外键,我们都想关联查询,参数 depth 的优势就凸显出来了,不需要详细写出每一个外键的名称。...如上示例,查询结果是一个 QuerySet 对象,为了使用方便,一般根据需要转换为 python 的列表。 3.annotate ❝聚合函数 ❞ 「需求」:统计出英雄表中男女的数量,显示聚合结果。
ele += td_ele return mark_safe(ele) (4)table_obj_list.html 首先要导入:{% load kingadmin_tags%} 然后使用自定义模板标签...:{% build_table_row obj admin_class %} 使用的时候需要传两个参数进去 {#kingadmin/templates/kingadmin/table_obj_list.html..._meta.fields 获取model所有字段的对象 models.CustomerInfo..../kingadmin_tags.py from django.template import Library from django.utils.safestring import mark_safe...%} 访问页面 接下来把数据返回到前端
models.CharField(max_length=32) age = models.IntegerField() user_type = models.ForeignKey('UserType')#外键...的get方法是从数据库的取得一个匹配的结果,返回一个对象,如果记录不存在的话,它会报错。...django的filter方法是从数据库的取得匹配的结果,返回一个对象列表,如果记录不存在的话,它会返回[]。 ? ORM的一对多: 我们在设计表结构的时候什么时候使用一对多呢?...中外键就相当于简单的使用__连表,在外键那个对象中封装了user_type表中的所有字段 我们要查询所有用户为CEO的用户,我们是不是的根据UserType这张表去查,如果是跨表查询使用“双下划线” +...现在我们已经会了两种方式创建第三张表了,当我们使用自定义创建的第三张表的时候,在去添加数据的时候! 就不能使用第一种方式对象添加了!
因为这样它只会影响工作进程,不会影响进程外的分析查询,cron 任务等。 希望您使用的是持久的数据库连接,这样每次请求都不会再有连接开销。...事务操作通常会涉及用户和产品的一些属性,所以我们经常使用 select_related 来强制 join 并保存一些查询。 更新交易还会涉及获得一个锁来确保它不被别人获得。 现在,你看到问题了吗?...当 select_for_update 与 select_related 一起使用时,Django 将尝试获取查询中所有表的锁。 我们用来获取事务的代码尝试获取事务表、用户、产品、类别表的锁。...外键索引(FK Indexes) 创建模型时,Django 会在所有外键上创建一个 B-Tree 索引,它的开销可能相当大,而且有时候并不很必要。...在我们的例子中,假设组少于用户(一般),所以把用户列放在第一位会使组的二级索引变小。