2012-11-26 50 views
10

我有以下型號:如何更新已註釋的查詢集?

class Work(models.Model): 
    visible = models.BooleanField(default=False) 

class Book(models.Model): 
    work = models.ForeignKey('Work')  

我試圖更新,像這樣一些行:

qs=Work.objects.all() 
qs.annotate(Count('book')).filter(Q(book__count__gt=1)).update(visible=False) 

但是,這給了一個錯誤:

DatabaseError:子查詢中有太多列 LINE 1:... SET「visible」= false WHERE「app_work」。「id」IN(SELECT ...

如果我刪除t他更新子句,查詢運行沒有問題,並返回我所期待的。

看起來這個錯誤發生在帶有註釋和後續更新的查詢上。有沒有其他的方式來寫這個?

回答

10

沒有使玩具數據庫能夠複製您的問題並嘗試解決方案,我至少可以建議Django: Getting complement of queryset的方法作爲一種可能的方法。

試試這個辦法:

qs.annotate(Count('book')).filter(Q(book__count__gt=1)) 
Work.objects.filter(pk__in=qs.values_list('pk', flat=True)).update(visible=False) 
+0

我其實不需要補充。查詢返回正確的行,但問題是我無法更新它們。 – jess

+0

對。我的意思是,你可以使用相同的基本方法來獲得應該是批量更新的unannotated查詢集。 – acjay

+2

@jess:我只是編輯了一個包含我的意思的例子。讓我知道這是否有效 – acjay

2

您還可以清除掉註釋一個QuerySet很簡單:

qs.query.annotations.clear() 
qs.update(..) 

這意味着你只發射了一個查詢,而不是一個到另一個,,但如果您的查詢依賴註釋來過濾,則不要使用它。這非常適合剝離數據庫生成的連接以及我偶爾添加到模型默認查詢中的實用程序垃圾......但問題中的示例是這種情況無效的完美示例。

0

要添加到奧利的回答是:如果你需要你的註釋進行更新,然後首先做的過濾器和結果存儲在一個變量,然後調用無參數的過濾器上的查詢集訪問update功能,像這樣:

q = X.objects.filter(annotated_val=5, annotated_name='Nima') 
q.query.annotations.clear() 
q.filter().update(field=900)