Django 获取切片后,无法更新查询
我正在尝试这样做:Django 获取切片后,无法更新查询,django,django-queryset,Django,Django Queryset,我正在尝试这样做: UserLog.objects.filter(user=user).filter(action='message').filter(timestamp__lt=now)[0:5].update(read=True) 但我得到了这个错误: Cannot update a query once a slice has been taken. (使用django 1.2.1) 我做错了什么?正如错误所述,如果取出一个切片,就不能对查询集调用update() 原因是: 获取切片相
UserLog.objects.filter(user=user).filter(action='message').filter(timestamp__lt=now)[0:5].update(read=True)
但我得到了这个错误:
Cannot update a query once a slice has been taken.
(使用django 1.2.1)
我做错了什么?正如错误所述,如果取出一个切片,就不能对查询集调用
update()
原因是:
LIMIT
语句update
语句更新。。。哪里限制5
这是不可能的,至少在标准SQL中是不可能的。您不能这样做。从Django文档中:可以看到类似于以下内容的情况-我不确定在内部
QuerySet中执行限制是否会绕过切片后调用update()
的检查:
inner_q = UserLog.objects.filter(user=user,
action='message',
timestamp__lt=now).values('pk')[0:5]
UserLog.objects.filter(pk__in=inner_q).update(read=True)
否则,您可以使用类似的方法:
在尝试限制查询集返回的记录数时,我遇到了相同的错误
我发现如果我们使用Django中的一个,比如,我们可以使用paginate\u by=
属性来限制记录的数量
例如(在views.py中):
如果您想切掉查询集的一些结果,可以复制它
将其复制到另一个变量(浅拷贝就足够了,这会更快)
而不是深度复制,因为它只使用对原始的引用
对象。)
这将防止Django抱怨,如果你有一个订单由过滤器上
你的桌子,因为如果你在主桌上做,那是在切片后发生的
queryset对象由于切片发生的位置,您的代码不正确。它应该发生在调用update()
之后,而不是之前
错:
UserLog.objects.filter(user=user).filter(action='message').filter(timestamp__lt=now)[0:5].update(read=True)
对:
UserLog.objects.filter(user=user).filter(action='message').filter(timestamp__lt=now).update(read=True)[0:5]
自Django 2.2以来,您可以使用批量更新:
queryset=UserLog.objects.filter(user=user.filter(action='message').filter(timestamp\uu lt=now)
批量=[]
对于用户登录queryset[0:5]:
userlog.read=True
bulk.append(userlog)
UserLog.objects.bulk\u更新(bulk,['read'])
非常感谢。我明白我的错误了。有什么解决办法吗?(除了在pks上循环并更新每个pks之外?UPDATE…其中…LIMIT 1在MySQL中是可能的。避免“选择…进行更新”锁定非常有用。@如果您是对的,我稍微扩展了我的答案。请注意,OP从未提及所使用的数据库类型。只要不需要分页,这是非常好和干净的。我想你也可能会抱怨你把代码弄得不清楚,因为你说它是分页的,但是没有在模板中分页,但是它比其他方法更快、更容易看出发生了什么。你可能应该把它们放在“with transaction.atomic():”块中。谢谢你的贡献。只提供代码作为答案并不能清楚地帮助OP和读者标记为正确答案。如果您提供此代码解析查询的原因和方式,这将非常有用。你在OP的代码中做了哪些更改,以解决查询。我知道。但就我而言,我不明白他的答案。然后,我这样做,我的问题就解决了。我的问题也一样。这就是为什么我把我的答案放在这里。这是一个错误的(甚至可能是危险的)答案。OP显然想更新前五个结果。我很确定你的代码会更新所有结果,然后它会抛出一个错误,因为update
返回行数,并且你不能切片一个整数。这是非常低效的,因为它会加载Mytable中的所有项。
import copy
queryset = Mytable.objects.all()
pieceOfQuery = copy.copy(queryset)
pieceOfQuery = pieceOfQuery[:10]
UserLog.objects.filter(user=user).filter(action='message').filter(timestamp__lt=now)[0:5].update(read=True)
UserLog.objects.filter(user=user).filter(action='message').filter(timestamp__lt=now).update(read=True)[0:5]