2013-10-04 37 views
0

我知道,Django querysey是一個生成器,而不是一個列表。爲什麼Django的查詢索引操作符返回對象的副本

my_items = Item.objects.filter(id = 1) 
my_items[0].name = 'joe' 
my_items[0].save() 

在示例中,my_items [0]是對象的副本,因此保存不會修改對象。
而這將工作(不會創建一個副本)在Django文檔

my_items = Item.objects.filter(id = 1) 
my_item = my_items[0] 
my_item.name = 'joe' 
my_item.save() 

凡(或任何別的地方),它解釋這種現象? 爲什麼他們選擇返回對象的副本而不是對象本身?

回答

4

它記錄在the section about querysets and caching。它不只是一個現有對象的副本。每次你這樣做,Django都會對數據庫進行單獨的查詢,並根據響應創建一個新對象。這裏是由文檔提供了一個例子:

>>> queryset = Entry.objects.all() 
>>> print queryset[5] # Queries the database 
>>> print queryset[5] # Queries the database again 

但是,如果你的查詢集已經評估,使用索引操作符不會碰到數據庫中獲取的對象,每一次你會得到相同的對象(如文檔中)。

更新:我被要求進一步clearify,所以這裏有雲:

你認爲你所得到的對象的副本,但是這並不完全正確。您將獲得兩個不同的Python對象,它們是獨立創建的,但基於相同的數據庫條目。這是因爲每次使用索引運算符時都會查詢數據庫並創建一個新對象(前提是查詢未被評估)。

在你的情況下,你使用操作符兩次,兩次都擊中數據庫。第一次在第二行:my_items[0].name = 'joe';第二行在第三行:my_items[0].save()。每次你做my_items[0]你正在使用操作符,查詢數據庫並創建一個新的對象。結果你保存了一個不同於你修改的對象。

+0

但你的描述不是我的問題 - 查詢集尚未評估。我的問題是獲取對象和對象本身的副本。 – yossi

+0

我不明白這不是你的問題。您沒有準確地獲取相同的對象*,因爲*查詢集之前未進行評估,因此每次使用索引運算符時都會查詢數據庫並創建一個新對象。你*認爲*你得到了對象的*副本,但這不是完全正確的。您將獲得兩個不同的Python對象,它們是獨立創建的,但基於相同的數據庫條目。 –

+0

我只使用索引運算符一次,就像你說的查詢集未被評估過。我的問題是爲什麼在評估之後,我得到了一份而不是原件。看看我添加到問題的代碼。如果你說我只想我得到一個對象的副本,那麼爲什麼保存方法不會將它保存到對象? – yossi

0

您在第二行寫「my_itMes」的事實是否重要?

Item.objects.filter(pk = 1).update(name = 'Joe') 

OR

myitem = Item.objects.get(id=1) 
myitem.name = 'joe' 
myitem.save() 

而且你問的文檔:

https://docs.djangoproject.com/en/1.5/topics/db/queries/#filtered-querysets-are-unique

每次細化查詢集的時候,你會得到一個全新的QuerySet這絕不會綁定到以前的QuerySet。每個優化都會創建一個獨立且不同的QuerySet,可以存儲,使用和重用。

+0

不,我錯了一個錯字:) – yossi

+0

謝謝你的回答,但我知道如何使它工作。那不是我的問題。 – yossi

+0

我爲你的問題添加了文檔。 –

相關問題