Warum funktioniert prejetch_related () von django nur mit all () und nicht filter ()?
glaube, ich habe dieses Modell:
class PhotoAlbum(models.Model):
title = models.CharField(max_length=128)
author = models.CharField(max_length=128)
class Photo(models.Model):
album = models.ForeignKey('PhotoAlbum')
format = models.IntegerField()
Nun, wenn ich will, zu betrachten eine Teilmenge von Fotos in einer Untergruppe der Alben effizient. Ich Tue es so etwas wie dieses:
someAlbums = PhotoAlbum.objects.filter(author="Davey Jones").prefetch_related("photo_set")
for a in someAlbums:
somePhotos = a.photo_set.all()
Dieser hat nur zwei Abfragen, die ist, was ich erwarte (um die Alben, und dann, eines wie `SELECT * Fotos, WO photoalbum_id IN ().
Alles Super.
Aber wenn ich dies Tue:
someAlbums = PhotoAlbum.objects.filter(author="Davey Jones").prefetch_related("photo_set")
for a in someAlbums:
somePhotos = a.photo_set.filter(format=1)
Dann macht es eine Tonne von Abfragen mit WHERE format = 1
! Mache ich etwas falsch oder ist django nicht schlau genug, um zu realisieren, hat er bereits geholt, alle Fotos und können die filter in python? Ich schwöre, ich habe irgendwo gelesen, in der Dokumentation, die Sie tun soll,...
InformationsquelleAutor der Frage Timmmm | 2012-10-19
Du musst angemeldet sein, um einen Kommentar abzugeben.
In Django 1.6 und früher, es ist nicht möglich zu vermeiden, und die zusätzlichen Abfragen. Die
prefetch_related
Anruf effektiv speichert die Ergebnisse dera.photoset.all()
für jedes album in den queryset. Allerdingsa.photoset.filter(format=1)
ist eine andere queryset, so dass Sie erzeugen eine zusätzliche Abfrage für jedes album.Erklärt ist das in der
prefetch_related
docs. Diefilter(format=1)
entsprichtfilter(spicy=True)
.Beachten Sie, dass Sie könnte reduzieren die Anzahl oder Abfragen, die eine Filterung der Fotos in python statt:
In Django 1.7, es ist ein
Prefetch()
Objekt, können Sie Steuern das Verhalten vonprefetch_related
.Weitere Beispiele, wie die
Prefetch
Objekt finden Sie in derprefetch_related
docs.InformationsquelleAutor der Antwort Alasdair
Aus der docs:
In deinem Fall "ein.photo_set.filter(format=1)" wird behandelt wie ein frische-Abfrage.
Darüber hinaus "photo_set" ist ein reverse-lookup - Umsetzung durch einen anderen manager zusammen.
InformationsquelleAutor der Antwort Ngure Nyaga