2010-11-26 3 views

Antwort

17

Wie der Fehler angibt, können Sie update() nicht auf einem QuerySet aufrufen, wenn Sie ein Segment herausgenommen haben.

Der Grund:

  1. ein Stück zu nehmen ist gleichbedeutend mit einer LIMIT Anweisung in SQL.
  2. Das Ausgeben eines Updates verwandelt Ihre Abfrage in eine UPDATE-Anweisung.

Was Sie versuchen, das entspricht

UPDATE ... WHERE ... LIMIT 5

zu tun wäre, was nicht möglich ist, zumindest nicht mit Standard-SQL.

+5

Vielen Dank tun. Ich sehe meinen Fehler. Gibt es einen Workaround dafür? (außer Schleifen über die PKs und Aktualisieren von jedem?) – xpanta

+0

'UPDATE ... WHERE ... LIMIT 1' ist in MySQL möglich. Ziemlich nützlich, um "SELECT ... FOR UPDATE" -Sperren zu vermeiden. – est

+0

@est du bist richtig, ich habe meine Antwort etwas erweitert. Beachten Sie, dass OP den Typ der verwendeten Datenbank nie erwähnt. –

43

Die documentation suggests, die so etwas wie die folgenden möglich sein könnte - ich bin die Prüfung nicht sicher, ob die Begrenzung, wenn dadurch in einem inneren QuerySet umgeht um update() nach dem Schneiden Aufruf:

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) 

Gelingt das nicht, Sie die in field lookup wie so verwenden könnte:

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) 
+2

erste Methode funktionierte für mich. habe den zweiten nicht versucht. –

+0

nicht threadsicher. benutze "SELECT ... FOR UPDATE" – est

+1

Wahrscheinlich sollte man diese "mit transaction.atomic():" blockieren. –

1

ich war immer die gleiche err oder wenn Sie versuchen, die Anzahl der von einem Abfrage-Set zurückgegebenen Datensätze zu begrenzen.

fand ich, dass, wenn wir einen von Djangos class-based generic views wie die ArchiveIndexView verwenden, können wir die paginate_by = Attribut verwenden, um die Anzahl der Datensätze zu begrenzen.

Zum Beispiel (in 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 
+1

Dies ist ziemlich schön und sauber, solange Sie nicht Paginierung wollen. Ich schätze, du könntest auch meckern, dass du den Code unklar machst, da du sagst, dass er paginiert ist, aber dann nicht in der Vorlage paginiert, aber es ist viel schneller und leichter ersichtlich, was passiert als andere Methoden. –

0

Wenn Sie möchten, einige der Ergebnisse einer queryset schneiden, können Sie es kopieren es auf eine andere Variable (eine flache Kopie ist genug, das ist schneller als eine tiefe Kopie, weil es nur auf die Original- Objekte verwendet.)

import copy 

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

Diese Django halten von beschweren, wenn Sie einen order_by Filter haben auf Ihre ta ble, da dies nach dem Schneiden passiert, wenn Sie es auf der Haupt Queryset-Objekt