我有一个简单的django的查询集,如:
qs = AModel.objects.exclude(state="F").order_by("order")
我想按如下方式使用它:
qs[0:3].update(state='F')
expected = qs[3] # throws error here
但最后一条声明抛出: “切片拍摄后无法更新查询。”
如何复制查询集?
答案 0 :(得分:2)
这是抛出错误的第一行:你不能做qs [0:3] .update()。 qs [0:3]正在筹码; update()正在更新查询。
update()用于批量更新,从而导致SQL查询,如
UPDATE app_model SET state = 'F' WHERE state <> 'F';
您正在尝试根据“订单”更新前三个项目,但使用此类型的更新无法完成 - 您无法订购或限制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不能为你做到这一点。
答案 1 :(得分:1)
你可以这样做:
qs = AModel.objects.filter(id__in=
AModel.objects.exclude(state="F").order_by("order")[10]).update()
答案 2 :(得分: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')
我使用exclude来删除不需要的元素,但这只有在订单是唯一的情况下才有效,否则您将无法知道更新的数量。如果订单不是唯一的,仍然可以按顺序使用第二个和唯一的arg:
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])
...