Django:获取切片后无法更新查询

时间:2010-11-26 12:52:23

标签: 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)

我做错了什么?

7 个答案:

答案 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()

原因:

  1. 获取切片相当于SQL中的LIMIT语句。
  2. 发布更新会将您的查询转换为UPDATE语句。
  3. 您要做的事情等同于

    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]