2013-12-19 63 views
1

用的方法來獲取所有相關的連接,它更好只返回一個QuerySet,或通過查詢集迭代返回ID列表?Django的方法返回

示例代碼:

class Foo(models.Model): 
    bar = models.ForeignKey(Bar, related_name="foos") 

class Bar(models.Model): 
    is_active = models.BooleanField(default=True) 

    def get_foos(self): 
     #this is the method to focus on for the question 

返回一個查詢集所有需要在get_foos如下:

return self.foos.all() 

但要獲得ID列表,那就要看看因此:

foos = self.foos.all() 
ids = [] 
for foo in foos: 
    ids.append(foo.pk) 
return ids 

我正在通過API看,他們使用後者,但我做不太明白爲什麼你會真的這樣做,如果你可以像前一樣做一個單線程! 有人可以解釋這些方法的好處嗎?如果有特定情況下哪一個比另一個更好?

回答

4

你可以得到富IDS在一條線:

ids = self.foos.values_list('pk', flat=True) 

使用ID列表,如果在其他表達式中使用更有效,如:

my_query.filter(foo__pk__in=ids) 
+2

只是爲了記錄:至少MySQL的是更高效的編寫過濾子句'my_query.filter(foo__pk__in =名單(IDS))',因爲它會避免子查詢。 –

-1

我不認爲這是一個更好還是更壞的情況。也可以用一行代碼生成的ID列表:

list(self.foos.values_list('pk', flat=True)) 

它有時好的做法的函數返回所請求的數據的最小或最強大的表現。也許你不希望來電者訪問queryset對象。

也許這些ID是要在模板渲染引擎,你寧願沒有跟來查詢集寫訪問模板,例如。

+0

'[foo.pk用於self.foos.all FOO()]'被更好寫入'列表(self.foos.values_list( 'pk' 中,扁平= TRUE))'。 –

+0

更正,謝謝 – slezica

1

如果你真的看到一些已發佈的應用像你的第二個片段,然後你可以向他們發送一個補丁(也可能不止一個,因爲很可能你會發現在這個程序了很多不好的代碼)。要點是:有很多寫得很差的Django應用程序。正如Niekas所發佈的那樣,您可以通過簡單易懂的單線電話獲得相同的結果和更好的表現。

現在wrt /爲什麼要返回一個pks列表而不是一個完整的查詢集,好吧,有時候這真的只是你需要的,有時候這很愚蠢 - 實際上取決於上下文。