2009-07-23 83 views
1

我有一个简单的Django的查询设置,如:重复的Django查询集?

qs = AModel.objects.exclude(state="F").order_by("order") 

我想如下使用它:

qs[0:3].update(state='F') 
expected = qs[3] # throws error here 

但最后一条语句抛出: 一次切片具有“无法更新查询被采取了“。

如何复制查询集?

回答

2

这是引发错误的第一行:您无法执行qs [0:3] .update()。 qs [0:3]正在切片; update()正在更新查询。

更新()是为批量更新,导致SQL查询,如

UPDATE app_model SET state = 'F' WHERE state <> 'F'; 

你试图根据“订单”更新前三个项目,但不能用这个做UPDATE类型 - 您不能排序或限制SQL UPDATE。它需要有不同的写法,例如。

UPDATE app_model SET state = 'F' WHERE id IN (
    SELECT id FROM app_model WHERE state <> 'F' ORDER BY order LIMIT 3 
) AS sub; 

但是Django不能为你做到这一点。

0

已经有一些关于使查询集切片成为可能并且能够在之前使用更新的讨论,但是AFAIK从来没有做过任何事情。我不认为你可以复制一个查询集的切片,但在这种情况下,你不需要。如果您的订单是一个唯一的整数,你将能够做到这一点:

qs = AModel.objects.exclude(state="F").order_by("order") 
if len(qs) > 3: 
    slice = qs.exclude(order__gt=qs[3]) 
else: 
    slice = qs 
slice.update(state='F') 

我用排除删除不需要的元素,但是这个如果订单是唯一只会工作,否则你将无法知道你有多少更新。如果为了不唯一会为了使用第二和独特的阿根廷仍然是可能的:

qs = AModel.objects.exclude(state="F").order_by("order", "pk") 
if len(qs) > 3: 
    slice = qs.exclude(order__gt=qs[3]).exclude(order=qs[3], pk__gt=qs[3]) 
... 
+0

注意,这非原子,即使是在一个交易(至少在Postgres中),除非你先取出表锁。 – 2009-07-23 09:46:48

1

你可以这样做:

qs = AModel.objects.filter(id__in= AModel.objects.exclude(state="F").order_by("order")[10]).update()