Django select_related不起作用

use*_*717 2 python django django-orm

我的Django select_related很奇怪

Models:
class Publisher(models.Model):
 name = models.CharField(max_length=100)
 class Meta:
      app_label = 'models'
      db_table = 'Publisher'
class Book(models.Model):
 name = models.CharField(max_length=100)
 publisher = models.OneToOneField(Publisher)
 class Meta:
      app_label = 'models'
     db_table = 'Book'
Run Code Online (Sandbox Code Playgroud)

输出:

books = Book.objects.select_related('publisher').all()
print books.query
SELECT "Book"."id", "Book"."name", "Book"."publisher_id", "Publisher"."id", "Publisher"."name" FROM "Book" INNER JOIN "Publisher" ON ( "Book"."publisher_id" = "Publisher"."id" )
print books.values()
[{'publisher_id': 1, u'id': 1, 'name': u'rest framework'}]
Run Code Online (Sandbox Code Playgroud)

Django会生成正确的查询,并在我执行它时检索数据。但是值不包含发布者

pco*_*nel 5

您有点误解了selected_related工作原理。参考django文档select_related

select_related返回一个QuerySet,它将“遵循”外键关系,并在执行查询时选择其他相关对象数据。 这可以提高性能,从而导致单个更复杂的查询,但意味着以后使用外键关系将不需要数据库查询。

正如您已经确定的那样,添加select_related会使django选择相关对象的数据(在本例中为Publisher.idPublisher.name)。但是,该all()方法仍将仅返回BookQuerySet。

哪里是当您访问,这是非常有用BookPublisher,Django将不需要再次查询数据库为Publisher

# Hits the database.
# SELECT "Book"."id", "Book"."name", "Book"."publisher_id" ...
b = Book.objects.get(name='Twilight')

# Hits the database again to get the related Book object.
# SELECT "Publisher"."id", "Publisher"."name" ...
p = b.publisher
Run Code Online (Sandbox Code Playgroud)

那是两个数据库查询,而select_related查找只是一个:

# Hits the database, but already includes Publisher data in the query
# SELECT "Book"."id", "Book"."name", "Book"."publisher_id", "Publisher"."id", "Publisher"."name" ...
b = Entry.objects.select_related('publisher').get(name='Twilight')

# Doesn't hit the database, because b.publisher has been prepopulated
# in the previous query.
p = b.publisher
Run Code Online (Sandbox Code Playgroud)

(示例与django docs示例略有不同)

  • 为什么在示例中使用“Entry”? (2认同)