2010-11-26 1 views

ответ

17

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

Причина:

  1. Принимая кусочек эквивалентно LIMIT заявление в SQL.
  2. Выдача обновления превращает ваш запрос в оператор UPDATE.

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

UPDATE ... WHERE ... LIMIT 5

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

+5

Большое спасибо. Я вижу свою ошибку. Есть ли обходной путь для этого? (кроме циклов на pks и обновления каждого из них?) – xpanta 2010-11-26 14:28:07

+0

`UPDATE ... WHERE ... LIMIT 1` возможно в MySQL. Весьма полезно избегать блокировки «SELECT ... FOR UPDATE». – est 2015-08-26 09:58:47

+0

@ вы правы, я немного расширил свой ответ. Обратите внимание, что OP никогда не упоминает тип используемой базы данных. – 2015-08-26 11:51:43

43

documentation suggests что-то вроде следующего может возможно - я не уверен, если это предельное во внутренней 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 field lookup так:

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

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

Я нашел, что если мы используем один из class-based generic views 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

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

import copy 

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

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