2016-12-20 6 views
3

Gibt es eine effizientere Möglichkeit, dies vielleicht mit F-Ausdrücken zu tun? Einige, wie man das Schlagen der DB verringert?Django: Mehrere Objekte Attribute aktualisieren

# 1st way hits DB twice per object 
def something(): 
    pks = [4, 2, 1, 3, 0] 
    for i in range(len(pks)): 
    mymodel.objects.get(pk=pks[i]).update(attr=i) 

# 2nd way hits DB once per obj and once for the queryset 
def something(): 
    pks = [4, 2, 1, 3, 0] 
    order = Case(*[When(pk=pk, then=pos) for pos, pk in enumerate(pks)]) 
    query = mymodel.objects.filter(pk__in=pks).order_by(order) 
    for i in range(len(query)): 
    query[i].attr = i 
    query[i].save() 

Bearbeitung, um Variablen konsistent zu verschieben.

Antwort

3

Im Allgemeinen sollten mehrere Datenbankabfragen statt einer großen Abfrage vermieden werden. Ihr Fall scheint jedoch eine Ausnahme zu sein. (Hinweis: Ich mache diese Antwort basierend auf den bereitgestellten Informationen. Bitte bearbeiten Sie Ihre Frage nicht zu sagen, dass ich eigentlich meinte ....)

Die folgende Abfrage wird sehr schnell sein, egal wie viele Datensätze Sie haben, weil Es ruft ein einzelnes Element von einem Primärschlüssel ab. Alle RDBMS sind dafür ausgelegt, dies wirklich gut zu handhaben.

mymodel.objects.get(pk=a[i]) 

Hower können Sie Ihre Funktion effizienter wie diese machen:

def something(): 
    pks = [4, 2, 1, 3, 0] 
    for i in range(len(a)): 
    mymodel.objects.filter(pk=a[i]).update(attr=i) 

Nun trifft es die DB nur einmal pro Objekt. die obige Abfrage übersetzt nur in

UPDATE mapp_mymodel SET attr=i where pk=1 
+0

Können Sie den Unterschied zwischen Get und Filter erklären? Sie sagen, dass get sehr schnell ist, weil es ein Element abruft, aber Filter in Ihrem Code verwendet. Ich habe generell Filter benutzt, wenn ich mehr als ein Objekt haben wollte und für ein Objekt bekommen wollte. –

+0

Der Unterschied zwischen get und Filter besteht darin, dass get ein Objekt holt und dann das Update durchführt, wie Sie es entdeckt haben. Filter ruft tatsächlich nichts aus der Datenbank ab, bis Sie ein Segment daraus entnehmen oder es durchlaufen. – e4c5

+0

Ich dachte, das würde die DB 2 mal treffen, weil einmal das Objekt dann noch mal aktualisiert werden soll, um das Objekt zu aktualisieren. –

0

Wenn ich mich nicht irre, können Sie so etwas wie

pks = [4, 2, 1, 3, 0] 
mymodel.object.filter(pk__in=pks).update(attr='test') 

tun, wenn Sie die für Schleifenindex als Attributwert verwenden möchten, in denen dies nicht funktioniert.

+0

Nach der OP-qestion. wenn pk = i, attr = i (jeder Attr ist anders), habe ich diesen Vorbehalt zu meiner Antwort hinzugefügt. In der obigen Abfrage. attr = 1 für alle Instanzen – e4c5

+0

Dachte, dies könnte der Fall sein (daher die letzte Zeile der Antwort). Aber gepostet es nur incase. Ihre Antwort scheint hilfreicher zu sein. Danke .. – zubhav

+0

Ja ich verwende den Index als Wert für attr. –

Verwandte Themen