2013-03-29 6 views
13

Ich versuche Positionsfeld für alle Objekte in einer bestimmten Reihenfolge auf einmal in Django (Python) zu aktualisieren.Aktualisieren Sie alle Modelle auf einmal in Django

Dies ist, wie ich es jetzt getan habe, aber das Problem ist, dass es eine Menge von Abfragen macht.

servers = frontend_models.Server.objects.all().order_by('-vote_count') 

    i = 1 
    for server in servers: 
     server.last_rank = i 
     server.save() 
     i += 1 

Gibt es eine Möglichkeit mit

Model.objects.all().order_by('some_field').update(position=some_number_that_changes_for each_object) 

Danke zu aktualisieren!

+0

Sie möchten die übergebene Zahl für jedes Objekt erhöhen? –

+1

django Abfrage API habe nicht [Windows-Funktionen] (http://www.postgresql.org/docs/9.1/static/tutorial-window.html) (denke ich). Sie sollten [custom sql direkt] (https://docs.djangoproject.com/en/dev/topics/db/sql/#executing-custom-sql-directly) ausführen, wenn Ihr RDBMS über diese Funktion verfügt. – danihp

Antwort

5

Sie können den F() Ausdruck von django.db.models das gleiche tun:

Model.objects.all().order_by('some_field').update(position=F(some_field)+1) 

, die eine einzelne SQL-Abfrage generiert alle Spaltenwerte zu aktualisieren, so ist es auch mit der Datenbank effizient.

+0

Dies beantwortet die Frage des OP nicht, da F() nur basierend auf dem Wert eines Felds in der gleichen Zeile berechnet werden kann, anstatt über die Zeilen wie gewünscht zu inkrementieren. –

+0

Für das spezifizierte Problem kann es umgestaltet werden, um in der gleichen Zeile zu arbeiten; Nein? –

+1

Dies könnte nur funktionieren, wenn ich die vorherige Zeile mit F verwenden könnte (same_field_of_previous_row) + 1 – Byteme

0

Soweit ich weiß, bietet Djangos Objekt-relationales Mapping-System keine Möglichkeit, diese Update-Operation auszudrücken. Aber wenn Sie wissen, wie es in SQL zum Ausdruck bringen, dann können Sie es über eine custom SQL query laufen:

from django.db import connection 
cursor = connection.cursor() 
cursor.execute('''UPDATE myapp_server ...''') 

Verschiedene Datenbank-Engines ausdrücken diese Operation auf unterschiedliche Weise. In MySQL würden Sie diese Abfrage ausführen:

SET @rownum=0; 
UPDATE myapp_server A, 
     (SELECT id, @rownum := @rownum + 1 AS rank 
     FROM myapp_server 
     ORDER BY vote_count DESCENDING) B 
SET A.rank = B.rank 
WHERE A.id = B.id 

In PostgreSQL ich glaube, Sie

UPDATE myapp_server A, 
     (SELECT id, rownumber() AS rank 
     OVER (ORDER BY vote_count DESCENDING) 
     FROM myapp_server) B 
SET A.rank = B.rank 
WHERE A.id = B.id 

verwenden würde (aber das ist nicht getestet, also Vorsicht!).

Verwandte Themen