Django: невозможно обновить запрос после того, как был взят фрагмент - PullRequest
20 голосов
/ 26 ноября 2010

Я пытаюсь сделать это:

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)

Что такоеЯ делаю не так?

Ответы [ 5 ]

53 голосов
/ 26 ноября 2010

Документация предполагает , что возможно что-то вроде следующего , возможно - я не уверен, что если ограничение во внутреннем 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)

В противном случае вы можете использовать поиск поля in примерно так:

ids = UserLog.objects.filter(user=user,
                             action='message',
                             timestamp__lt=now).values_list('pk', flat=True)[0:5]
UserLog.objects.filter(pk__in=list(ids)).update(read=True)
20 голосов
/ 26 ноября 2010

Как гласит ошибка, вы не можете вызвать update() в QuerySet, если вы вынули ломтик.

Причина:

  1. Взятие слайса эквивалентно *Оператор 1007 * в SQL.
  2. Выпуск обновления превращает ваш запрос в оператор UPDATE.

То, что вы пытаетесь сделать, будет эквивалентно

UPDATE ... WHERE ... LIMIT 5

, что невозможно, по крайней мере, для стандартного SQL.

2 голосов
/ 27 апреля 2013

Я получал ту же ошибку при попытке ограничить количество записей, возвращаемых набором запросов.

Я обнаружил, что если мы используем одно из универсальных представлений на основе классов Django например, 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
0 голосов
/ 14 марта 2014

Если вы хотите вырезать некоторые результаты из набора запросов, вы можете скопировать его это к другой переменной (достаточно мелкой копии, которая быстрее чем глубокая копия, потому что он просто использует ссылки на оригинал объекты.)

import copy

queryset = Mytable.objects.all()
pieceOfQuery = copy.copy(queryset)
pieceOfQuery = pieceOfQuery[:10]

Это удержит Django от жалоб, если у вас включен фильтр order_by ваш стол, так как это происходит после нарезки, если вы делаете это на главной объект набора запросов

0 голосов
/ 26 ноября 2010

Вы не можете этого сделать.Из документов Django: Справочник по QuerySet API - обновление

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...