2013-03-18 19 views
1

我有一个2模型,一个房子和一条消息。一个消息有FK一所房子:Django:推迟并且不工作

model House: 
    attribute1 = models.CharField("") 
    ...more stuff... 

model Message: 
    house = models.ForeignKey(House) 
    ...more stuff... 

我创建15个消息的所有与house_id = 3使用:消息(house_id = 3).save()

我的问题是该查询是如何缓慢服用。当我这样做:

Message.objects.filter(house_id = 3) 

我得到以下查询:

{u'time': u'0.030', u'sql': u'SELECT `home_message`.`id`, `home_message`.`house_id`,  FROM `home_message` WHERE `home_message`.`house_id` = 3 '} 
{u'time': u'0.027', u'sql': u'SELECT `home_house`.`id`, `home_house`.`is_active`, FROM `home_house` WHERE `home_house`.`id` = 3 '} 
{u'time': u'0.027', u'sql': u'SELECT `home_house`.`id`, `home_house`.`is_active`, FROM `home_house` WHERE `home_house`.`id` = 3 '} 
{u'time': u'0.027', u'sql': u'SELECT `home_house`.`id`, `home_house`.`is_active`, FROM `home_house` WHERE `home_house`.`id` = 3 '} 

...(15次,每一个消息)

所以我看到,我得到一个数据库查询为我的消息中的每个house_id。请注意,我只查询消息一次(如预期)。

显然,这是相当缓慢的,所以我尝试:

Message.objects.filter(house_id = 3).defer( '家')

令人惊讶的,这使得它更糟糕。该查询现在是:

{u'time': u'0.028', u'sql': u'SELECT `home_message`.`id` FROM `home_message` WHERE `home_message`.`house_id` = 3 '} 
{u'time': u'0.024', u'sql': u'SELECT `home_message`.`id`, `home_message`.`house_id` FROM `home_message` WHERE `home_message`.`id` = 1 '} 
{u'time': u'0.027', u'sql': u'SELECT `home_house`.`id`, `home_house`.`is_active`, ` FROM `home_house` WHERE `home_house`.`id` = 3 '} 
{u'time': u'0.024', u'sql': u'SELECT `home_message`.`id`, `home_message`.`house_id` FROM `home_message` WHERE `home_message`.`id` = 2 '} 
{u'time': u'0.027', u'sql': u'SELECT `home_house`.`id`, `home_house`.`is_active`, ` FROM `home_house` WHERE `home_house`.`id` = 3 '} 
...x15... 

我现在正在做一个查询每个单独的消息,并为每家外键 - 本质上加倍的呼叫数量。

这没有奏效。所以现在我尝试django“唯一”。
Message.objects.filter(house_id = house_id).only(“id”)。 #只有ID!

的查询现在我给:

{u'time': u'0.025', u'sql': u'SELECT `home_message`.`id` FROM `home_message` WHERE `home_message`.`house_id` = 3 '} 
{u'time': u'0.024', u'sql': u'SELECT `home_message`.`id`, `home_message`.`house_id` FROM `home_message` WHERE `home_message`.`id` = 1 '} 
{u'time': u'0.026', u'sql': u'SELECT `home_house`.`id`, `home_house`.`is_active`, WHERE `home_house`.`id` = 3 '} 
{u'time': u'0.024', u'sql': u'SELECT `home_message`.`id`, `home_message`.`house_id` FROM `home_message` WHERE `home_message`.`id` = 2 '} 
{u'time': u'0.026', u'sql': u'SELECT `home_house`.`id`, `home_house`.`is_active`, WHERE `home_house`.`id` = 3 '} 

... ... X15的

所以再次,我得到了可怕的房子对象查询和通过ID另一查询已满消息(像延期命令)。

我不明白这是ONLY和DEFER的正确行为。我只希望获得信息(作为一个对象,或者我会使用“值” - 它可以顺利运行),而不需要评估FK。

编辑:

错误是在unicode的,我叫 回报self.house

回答

0

你似乎有对一般的Django的查询集的几个误解,什么deferonly应该特别要做。

defer(fieldname)意思是“现在不要查询'字段名',等到我稍后再问”。所以很自然,因为你随后会立即要求'house',你会得到双重查询。

only(fieldname)意思是 - 顾名思义 - “只给我'字段名'”。所以我不知道为什么你会感到惊讶,然后引用其他字段而不是'ID'会触发进一步的查询。

但是,您应该注意,这两者都与您的实际问题没有任何关系:正确使用的工具是select_related(),正如文档解释的那样,它用于在单个查询中跟踪ForeignKey。

+0

我对“延迟”查询的理解似乎与您匹配,但我可能会错误地使用它?当我这样做时:Message.objects.filter(house_id = 3).defer('house'),我认为它应该推迟“house”的呼叫,但你仍然可以通过house_id进行过滤。我不明白我在代码中要求“房子”的地方? 关于“only(fieldname)”,我并不要求任何其他信息。我告诉它打印返回的查询: print(Message.objects.filter(house_id = house_id).only(“id”))。我是否喜欢呼吁其他的域名? 另外我会看看select_related。 – user1639926 2013-03-19 00:09:00