2010-11-21 14 views
0

Ich habe eine Liste von Objekten:Modelldaten mit der Liste von Objekten Kombinieren

film_hc = [{'count': 2, 'pk': '33'}, 
      {'count': 1, 'pk': '37'}, 
      {'count': 1, 'pk': '49'}] 

Der ‚pk‘ Wert der Primärschlüssel für einen Datensatz in einem Modell. Ich möchte das Namensfeld dieses Datensatzes zu dieser Liste von Objekten hinzufügen. Um einen Namen zu bekommen, kann ich verwenden:

record = Film.objects.get(pk = film_hc[0]['pk']) 
record.name 

Am Ende würde Ich mag so etwas haben:

film_hc = [{'count': 2, 'pk': '33', 'name': 'name1'}, 
      {'count': 1, 'pk': '37', 'name': 'name2'}, 
      {'count': 1, 'pk': '49', 'name': 'name3'}] 

Frage: Was ist der effizienteste Weg, um die notwendigen Daten befestigen zu dieser bereits bestehenden Liste?

Ich denke ich die Zip-Funktion verwenden:

film_hc_with_names = zip(????, film_hc) 

Das Problem ist, ich bin nicht sicher, was ich anstelle derer ersetzen würde ???? um das Objekt zu erhalten, dann den Namen für jedes Objekt in der Liste. Soll ich stattdessen eine for-Schleife verwenden? Was ist die beste Option?

Antwort

1

Um zu vermeiden, die Datenbank mehrmals zu schlagen, empfehle ich Ihnen, die in_bulk Methode queryset zu verwenden. Dies nimmt eine Liste von IDs und gibt ein Wörterbuch der ID zurück, das der Modellinstanz zugeordnet ist. Sie müssen also zuerst Ihre Wörterlisten durchgehen, um die ID-Werte zu extrahieren, dann die Abfrage ausführen und dann erneut durchgehen, um den Namen für jede Instanz zu erhalten. Obwohl dies zwei zusätzliche Iterationen durchführt, sollte es dennoch schneller sein als das Ausführen mehrerer DB-Abfragen (obwohl Sie wie immer ein Profil erstellen sollten, um sicher zu gehen).

id_list = [film['id'] for film in film_hc] 
objects = Film.objects.only('name').in_bulk(id_list) 
for film in film_hc: 
    film['name'] = objects[film['id']].name 
+0

Ich werde definitiv eine Verwendung von in_bulk irgendwann finden. In diesem Fall weiß ich nicht, dass es sinnvoll ist, zweimal zu iterieren. Scheint so, als könnten wir es in einem tun. –

+0

@Ed natürlich liegt das an dir, aber du solltest dich nicht nur auf die Iteration als Hauptinnektivität konzentrieren. Ein mehrfaches Aufeinandertreffen der Datenbank ist viel ineffizienter. Ein schneller Test, der "ab" für 100 Treffer gegen meinen Code gegen aaronsterlings oben zeigt, zeigte 0,370ms für meine vs 0,542ms für seine: also ist meine Methode ungefähr 50% effizienter. –

+0

hmm. Du hast recht. Getestet und das funktioniert viel schneller. Danke für das Follow-up. –

Verwandte Themen