2017-01-10 1 views
2

Ich habe das folgende Modell.Django - Optimieren Abfragen mit select_related()

class Car(models.Model): 
    owner = models.ForeignKey('Driver') 

class Country(models.Model) 
    name = models.CharField(max_length=255) 

class Driver(models.Model): 
    name = models.CharField(max_length=255) 
    age = models.IntegerField() 
    country = models.ForeignKey('Country') 

Ich möchte den Namen der Fahrer, die ein Auto besitzen, auswählen.

Car.objects.all().values('owner__name') 

Benötige ich, select_related() -Methode verwendet eine für jedes Objekt verbinden zu vermeiden, oder es ist überflüssig, weil implizit mit Werten() Methode?

Car.objects.all().select_related('owner').values('owner__name') 

In gleicher Weise mag ich diesmal die Namen der Länder mit den Fahrern ein Auto zu besitzen. Welches ist das beste?

Car.objects.all().values('owner__country__name') 
Car.objects.all().select_related('owner', 'country').values('owner__country__name') 
Car.objects.all().select_related('owner__country').values('owner__country__name') 
+0

Der letzte Teil ich nehme an, Sie 'Driver.objects.filter wollen (car__isnull = False, ...)' aber Ihre Frage ist ein bisschen breit, Sie sollten es auf die erste Frage über implizite Joins beschränken – Sayse

+1

Danke, bearbeite ich die Frage, um den Anwendungsbereich auf die Verwendung von select_related() zu reduzieren. – srjjio

Antwort

2

Zuerst werden alle Vorkommen von .all() in Ihre Beispiele können gelöscht werden; Der Manager (.objects) hat bereits fast alle Methoden des QuerySets, mit Ausnahme von .delete().

.select_related ist nur hilfreich, wenn Ihre eventuelle Abfrage Modellinstanzen zurückgibt; Dann wird der gesamte Fremdschlüssel jeder Instanz vorgeladen.

Aber wenn Sie .values verwenden, erhalten Sie Wörterbücher, und es gibt keine Fremdschlüsselattribute zum Vorladen. Daher sollte es in diesem Fall nicht verwendet werden.

Wenn Sie tun, .values('owner__name') Django sieht bereits, dass es Besitzer und Autos beitreten muss, keine zusätzlichen Abfragen durchgeführt werden.

Im letzten Sie Länder wollen, so verwenden Country.objects:

Country.objects.filter(driver__car__isnull=False).values('name') 
+0

Vielen Dank für Ihr Feedback. Aber selbst mit einem Diktat können wir uns vorstellen, dass Django eine neue Join-Abfrage in der Datenbank erstellen kann, um jedes Element zu iterieren. Aus diesem Grund möchte ich sicher sein, dass die Auswahl in diesem Fall nicht sinnvoll ist. – srjjio

Verwandte Themen