django-orm-select_related()函数

一:介绍

select_related函数:

 1     def select_related(self, *fields):
 2         """
 3         Returns a new QuerySet instance that will select related objects.
 4 
 5         If fields are specified, they must be ForeignKey fields and only those
 6         related objects are included in the selection.
 7 
 8         If select_related(None) is called, the list is cleared.
 9         """
10 
11         if self._fields is not None:
12             raise TypeError("Cannot call select_related() after .values() or .values_list()")
13 
14         obj = self._clone()
15         if fields == (None,):
16             obj.query.select_related = False
17         elif fields:
18             obj.query.add_select_related(fields)
19         else:
20             obj.query.select_related = True
21         return obj

 使用该函数的,他的返回值是一个和他相关联的对象新Queryset对象的集合。如果填写第二个参数的话,他必须是外键关联的对象。

有如下表结构:

 1 from django.db import models
 2 
 3 # Create your models here.
 4 class  Book(models.Model):
 5     name=models.CharField(max_length=32)
 6     author=models.ForeignKey('Author')
 7 
 8 
 9 class  Author(models.Model):
10     name=models.CharField(max_length=32)

 简单插入数据:

book表

author表:

select_related()函数:作用当我们在查询带有外键关联的表的对象的时候,正常查询是分2次查询:

比如上面的表结构:查询evil的对应的书籍。

1)首先我们在author表中查询到evil的对象:author_obj=models.Author.objects.filter(name='evil')

2)通过这个evil对象查询book对象:author_obj.book

如上是经过2次数据库的查询。而使用select_related函数的时候,只需查询一次数据库就可以获得相应的关联的(外键)的对象集合。

1 def check(request):
2     author=models.Author.objects.select_related().filter(name='evil').first()
3     book=author.book_set.all()
4     for i in book:
5         print(i.name)
6     return HttpResponse('ok')

 

select_related函数帮我们做了:在一次的查询中查询到对象集合以及和关联的对象的集合。可以直接获取相应的外键的对象列表。

在效率上比之前的分步查询上,效率高,

前提:查询的表和关联的表的层级不深和不多。情况下:效率高;

如果查询的表的层级比较多,关联的表较多(外键较多),会耗时。

参数:depth,执行获取关联对象的深度,如果depth=2,不仅能查询到作者关联的实体对象,而且还可以查询book关联(外键)的实体对象。默认情况将会获取到该作者的所有关联对象的 包括关联对象的子关联对象。

所以用他有利有弊,主要看表的关联复杂程度。

所以当我们获取对象需要它相关联的对象时,就请用select_related()吧,如果该对象关联的表很多,请指定depth的值,避免资源的浪费;反之避免select_related()。

 

posted @ 2016-11-28 15:16  evil_liu  阅读(2704)  评论(0编辑  收藏  举报