2012-11-26 14 views
10

Ich habe folgende Modelle:Wie Aktualisieren eines Anfragesatzes, der annotiert wurde?

class Work(models.Model): 
    visible = models.BooleanField(default=False) 

class Book(models.Model): 
    work = models.ForeignKey('Work')  

ich wie so einige Zeilen zu aktualisieren, bin versucht:

qs=Work.objects.all() 
qs.annotate(Count('book')).filter(Q(book__count__gt=1)).update(visible=False) 

Dies ist jedoch geben einen Fehler:

Database: Unterabfrage hat zu viele Spalten ZEILE 1: ... SET "sichtbar" = falsch WHERE "app_work". "id" IN (AUSWAHL ...

Wenn ich t entferne Er Update-Klausel, die Abfrage läuft ohne Probleme und gibt zurück, was ich erwarte.

Es sieht aus wie dieser Fehler für Abfragen mit einem Kommentar gefolgt von einem Update auftritt. Gibt es eine andere Möglichkeit, dies zu schreiben?

Antwort

10

Ohne eine Spielzeug-Datenbank zu erstellen, um Ihr Problem zu duplizieren und Lösungen auszuprobieren, kann ich zumindest den Ansatz in Django: Getting complement of queryset als einen möglichen Ansatz vorschlagen.

versuchen, diesen Ansatz:

qs.annotate(Count('book')).filter(Q(book__count__gt=1)) 
Work.objects.filter(pk__in=qs.values_list('pk', flat=True)).update(visible=False) 
+0

Ich brauche eigentlich nicht das Komplement. Die Abfrage gibt die richtigen Zeilen zurück, aber das Problem ist, dass ich sie nicht aktualisieren kann. – jess

+0

Rechts. Mein Punkt ist, dass Sie den gleichen grundlegenden Ansatz verwenden können, um ein unannoted Abfrage-Set zu erhalten, das Bulk-updateable sein sollte. – acjay

+2

@jess: Ich habe gerade bearbeitet, um ein Beispiel zu geben, was ich meinte. Lass es mich wissen, wenn das funktioniert – acjay

2

Sie können auch die Anmerkungen aus einem queryset löschen ganz einfach:

qs.query.annotations.clear() 
qs.update(..) 

Und das bedeutet, dass Sie abzufeuern nur eine Abfrage , nicht eins in das andere, , aber verwenden Sie dies nicht, wenn Ihre Abfrage auf eine Anmerkung zum Filtern angewiesen ist. Das ist großartig, um datenbankgenerierte Verkettungen zu entfernen, und den Utility-Müll, den ich gelegentlich den Standardabfragen von Modellen hinzufüge ... aber das Beispiel in der Frage ist ein perfektes Beispiel dafür, wo das nicht funktionieren würde.

0

zu Oli Antwort hinzuzufügen: Wenn Sie Ihre Anmerkungen für das Update benötigen, um die Filter zu tun dann erste und das Ergebnis in einer Variablen und rufen Sie dann Filter ohne Argumente auf dieser queryset wie so die update Funktion zuzugreifen:

q = X.objects.filter(annotated_val=5, annotated_name='Nima') 
q.query.annotations.clear() 
q.filter().update(field=900) 
Verwandte Themen