Django:ForeignKey数据库查询的数量

时间:2014-04-30 22:55:31

标签: sql django postgresql

我想澄清一些事情,以便我可以通过psycopg2适配器优化我的Django ORM查询到Postgres。

比如说我有三个模型:

from django.db import models   

class City(models.Model):
     #
     pass

class Person(models.Model):
     hometown = models.ForeignKey(City)

class Book(models.Model):
     author = models.ForeignKey(Person)

现在让我们进行以下查询:

book = Book.objects.get(pk = 4)

现在,如果我想知道作者的原始ID,我需要做的就是这个

>>> raw_id = book.author_id
>>> print raw_id
3

我的问题是,book.author_id是否会对数据库进行另一次点击,还是只是从内存中获取它,因为它已经从get查询中获取了?根据我的理解,这个查询应该只有一次旅行正确吗?

1 个答案:

答案 0 :(得分:4)

你是对的,book.author_id没有在数据库上再次命中,外键ID存储在书中。如果您使用DEBUG=True设置转到shell,您可以自己查看:

>>> from django.db import connection

>>> connection.queries
[]

>>> book = Book.objects.get(pk=4)

>>> connection.queries
[{u'sql': u'SELECT "yourapp_book"."id", "yourapp_book"."author_id" FROM "yourapp_book" WHERE "yourapp_book"."id" = 4 ',
u'time': u'0.003'}]

>>> book.author_id
7

>>> connection.queries
[{u'sql': u'SELECT "yourapp_book"."id", "yourapp_book"."author_id" FROM "yourapp_book" WHERE "yourapp_book"."id" = 4 ',
u'time': u'0.003'}]

>>> book.author
<Author: Mark Twain>

>>> connection.queries
[{u'sql': u'SELECT "yourapp_book"."id", "yourapp_book"."author_id" FROM "yourapp_book" WHERE "yourapp_book"."id" = 4 ',
 u'time': u'0.003'},
 {u'sql': u'SELECT "yourapp_author"."id", "yourapp_author"."name" FROM "yourapp_author" WHERE "yourapp_author"."id" = 7 ',
 u'time': u'0.001'}]

connection.queries列出了在DEBUG打开时通过django shell中的ORM发送的所有SQL查询。请注意,即使在执行book.author_id之后也只进行了一次查询,但是当我们执行book.author时会进行第二次查询,因为django必须返回数据库才能获取要显示的作者姓名。

您可以通过book = Book.objects.select_related('author').get(pk=4)选择图书来避免第二次数据库查询。

>>> connection.queries
[]

>>> book = Book.objects.select_related('author').get(pk=4)

>>> connection.queries
[{u'sql': u'SELECT "yourapp_book"."id", "yourapp_book"."author_id", 
  "yourapp_author"."id", "yourapp_author"."name"
  FROM "yourapp_book" LEFT OUTER JOIN "yourapp_author" ON 
  ( "yourapp_book"."author_id" = "yourapp_author"."id" ) WHERE "yourapp_book"."id" = 4 ',
  u'time': u'0.003'}]

>>> book.author
<Author: Mark Twain>

>>> connection.queries
[{u'sql': u'SELECT "yourapp_book"."id", "yourapp_book"."author_id", 
  "yourapp_author"."id", "yourapp_author"."name"
  FROM "yourapp_book" LEFT OUTER JOIN "yourapp_author" ON 
  ( "yourapp_book"."author_id" = "yourapp_author"."id" ) WHERE "yourapp_book"."id" = 4 ',
  u'time': u'0.003'}]

我还应该注意,为了调试在测试期间在运行的django应用程序中实际进行的查询数量,工具django-debug-toolbar是非常宝贵的。