Angenommen, 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 eine Teilmenge von Fotos in einer Teilmenge von Alben effizient betrachten möchte. Ich mache es so ähnlich:
someAlbums = PhotoAlbum.objects.filter(author="Davey Jones").prefetch_related("photo_set")
for a in someAlbums:
somePhotos = a.photo_set.all()
Dies führt nur zwei Abfragen aus, was ich erwarte (eine, um die Alben zu erhalten, und eine wie `SELECT * IN photos WHERE photoalbum_id IN ().
Alles ist großartig.
Aber wenn ich das mache:
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 Menge Abfragen mit WHERE format = 1
! Mache ich etwas falsch oder ist Django nicht klug genug, um zu erkennen, dass es bereits alle Fotos abgerufen hat und sie in Python filtern kann? Ich schwöre, ich habe irgendwo in der Dokumentation gelesen, dass es das tun soll ...
Antworten:
In Django 1.6 und früheren Versionen können zusätzliche Abfragen nicht vermieden werden. Der
prefetch_related
Aufrufa.photoset.all()
speichert die Ergebnisse für jedes Album im Abfrageset effektiv zwischen . Daa.photoset.filter(format=1)
es sich jedoch um ein anderes Abfrageset handelt, generieren Sie für jedes Album eine zusätzliche Abfrage.Dies wird in den
prefetch_related
Dokumenten erklärt. Dasfilter(format=1)
entsprichtfilter(spicy=True)
.Beachten Sie, dass Sie die Anzahl oder die Abfragen reduzieren können, indem Sie stattdessen die Fotos in Python filtern:
In Django 1.7 gibt es ein
Prefetch()
Objekt, mit dem Sie das Verhalten von steuern könnenprefetch_related
.Weitere Beispiele zur Verwendung des
Prefetch
Objekts finden Sie in denprefetch_related
Dokumenten.quelle
Aus den Dokumenten :
In Ihrem Fall wird "a.photo_set.filter (format = 1)" wie eine neue Abfrage behandelt.
Darüber hinaus ist "photo_set" eine umgekehrte Suche, die über einen anderen Manager implementiert wird.
quelle
photo_set
kann auch mit vorabgerufen werden.prefetch_related('photo_set')
. Aber Ordnung ist wichtig, wie Sie erklärt haben.