2013-03-29 13 views
13

Próbuję zaktualizować pole pozycji dla wszystkich obiektów w określonej kolejności naraz w Django (python).Zaktualizuj wszystkie modele naraz w Django

Tak właśnie to zrobiłem, ale problemem jest to, że robi mnóstwo zapytań.

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

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

Czy istnieje sposób, aby aktualizować z

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

Dziękujemy!

+0

Chcesz zwiększyć liczbę przekazanych dla każdego obiektu? –

+1

api zapytania django nie ma funkcji okna (http://www.postgresql.org/docs/9.1/static/tutorial-window.html) (myślę). Powinieneś wykonać [custom sql bezpośrednio] (https://docs.djangoproject.com/en/dev/topics/db/sql/#executing-custom-sql-directly), jeśli twój RDBMS ma tę funkcję. – danihp

Odpowiedz

5

Można użyć wyrażenia F() z django.db.models zrobić to samo:

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

który generuje pojedynczy zapytanie SQL, aby zaktualizować wszystkie wartości w kolumnie, więc jest skuteczny do bazy danych też.

+0

Nie odpowiada to na pytanie OP, ponieważ F() może obliczać tylko na podstawie wartości pola w tym samym wierszu, zamiast zwiększać liczbę wierszy, jak chce. –

+0

Dla określonego określonego problemu, może być refaktoryzowany do pracy w tym samym rzędzie; Nie? –

+1

może to działać tylko wtedy, gdybym mógł użyć poprzedniego wiersza z F (same_ pole_z_previous_row) + 1 – Byteme

0

O ile mi wiadomo, system mapowania obiektowo-relacyjnego Django nie zapewnia sposobu wyrażenia tej operacji aktualizacji. Ale jeśli wiesz, jak wyrazić to w SQL, a następnie można go uruchomić poprzez custom SQL query:

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

różnych silników baz danych wyrazić tę operację na różne sposoby. W MySQL chcesz uruchomić tę kwerendę:

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 

w PostgreSQL myślę byłoby użyć

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 

(ale to niesprawdzone, więc uwaga!).

Powiązane problemy