我正在尝试这样做:
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)
我做错了什么?
答案 0 :(得分:52)
documentation suggests类似以下的内容可能 - 我不确定在内部QuerySet
中进行限制是否会绕过调用{{1}的检查切片后:
update()
如果不这样做,您可以像in
field lookup那样使用:
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)
答案 1 :(得分:20)
如错误所述,如果您取出切片,则无法在QuerySet上调用update()
。
原因:
LIMIT
语句。UPDATE
语句。您要做的事情等同于
UPDATE ... WHERE ... LIMIT 5
这是不可能的,至少不是标准SQL。
答案 2 :(得分:2)
尝试限制查询集返回的记录数时,我遇到了同样的错误。
我发现如果我们使用Django的class-based generic views之一,例如ArchiveIndexView,我们可以使用paginate_by =
属性来限制记录数量。
例如(在views.py中):
from django.views.generic import ArchiveIndexView
from .models import Entry
class HomeListView(ArchiveIndexView):
""" Blog Homepage """
model = Entry
date_field = 'pub_date'
template_name = 'appname/home.html'
queryset = Entry.objects.filter(
is_active=True).order_by('-pub_date', 'title')
paginate_by = 30
答案 3 :(得分:2)
从 Django 2.2 开始,您可以使用批量更新:
queryset = UserLog.objects.filter(user=user).filter(action='message').filter(timestamp__lt=now)
bulk = []
for userlog in queryset[0:5]:
userlog.read = True
bulk.append(userlog)
UserLog.objects.bulk_update(bulk,['read'])
答案 4 :(得分:0)
你做不到。来自Django文档:QuerySet API reference - update
答案 5 :(得分:0)
如果要切出查询集的某些结果,可以复制它 它到另一个变量(浅拷贝就足够了,速度更快 而不是深拷贝,因为它只使用对原始的引用 对象。)
import copy
queryset = Mytable.objects.all()
pieceOfQuery = copy.copy(queryset)
pieceOfQuery = pieceOfQuery[:10]
如果你有一个order_by过滤器,这将使Django不抱怨 你的表,因为如果你在主要表面上进行切片,就会发生这种情况 queryset对象
答案 6 :(得分:-1)
您的代码不正确,因为发生切片的位置。应该在调用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]