重复的django查询集?

1 投票
3 回答
2492 浏览
提问于 2025-04-15 13:06

我有一个简单的 Django 查询集,像这样:

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

我想这样使用它:

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

但是最后这条语句报错了:

"一旦进行了切片,就无法更新查询。"

我该如何复制这个查询集呢?

3 个回答

0

之前有一些讨论,想要实现对查询集(queryset)进行切片,然后在这些切片上使用更新操作,但据我所知,这方面并没有实际的成果。我觉得你不能直接复制一个查询集的切片,但在这种情况下你其实不需要这样做。如果你的顺序是一个唯一的整数,你可以这样做:

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来去掉不需要的元素,但这只有在顺序是唯一的情况下才有效,否则你就无法知道你更新了多少个。如果顺序不是唯一的,仍然可以通过在顺序中使用第二个唯一的参数来实现:

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])
...
1

你可以这样做:

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

2

错误是出在第一行:你不能这样用 qs[0:3].update()。qs[0:3] 是在取一个切片;而 update() 是用来更新查询的。

update() 是用来批量更新的,生成的 SQL 查询看起来像这样:

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

你想根据“order”来更新前三个项目,但这种 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 不能为你做到这一点。

撰写回答