python / expert
Snippet
Django ORM-Abfrageoptimierung mit Prefetch Related
Dieses Expertenmuster demonstriert fortgeschrittene Django-ORM-Optimierung. Die Verwendung von Prefetch mit einem benutzerdefinierten Queryset filtert zugehörige Bücher, bevor sie in den Speicher geladen werden, und nutzt select_related, um den Verlag in derselben Abfrage abzurufen. Die only()-Methode begrenzt die abgerufenen Felder und reduziert den Speicherverbrauch. Ein benutzerdefinierter Manager kapselt diese Logik und macht sie über die gesamte Anwendung hinweg wiederverwendbar.
snippet.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
from django.db import modelsfrom django.db.models import Prefetchclass AuthorManager(models.Manager):def get_with_books(self):return self.get_queryset().prefetch_related(Prefetch('books',queryset=Book.objects.filter(is_published=True).select_related('publisher').only('id', 'title', 'published_date', 'publisher__name'),to_attr='published_books'))class Author(models.Model):name = models.CharField(max_length=200)objects = AuthorManager()class Meta:indexes = [models.Index(fields=['name'])]class Book(models.Model):author = models.ForeignKey(Author, on_delete=models.CASCADE, related_name='books')publisher = models.ForeignKey('Publisher', on_delete=models.CASCADE)is_published = models.BooleanField(default=False)
django
Erklärung
1
Prefetch('books', queryset=Book.objects.filter(...))
Erstellt ein Prefetch-Objekt, um zu steuern, wie zugehörige Bücher abgerufen und gefiltert werden
2
select_related('publisher')
Verbindet die Publisher-Tabelle in einer einzigen Abfrage und vermeidet N+1-Abfragen
3
only('id', 'title', 'published_date', 'publisher__name')
Begrenzt abgerufene Spalten auf nur das, was benötigt wird, reduziert Datentransfer
4
to_attr='published_books'
Speichert vorgefertigte Ergebnisse in einem Listenattribut anstatt im Queryset-Cache
5
models.Index(fields=['name'])
Index auf Datenbankebene für schnellere Suchvorgänge im Namensfeld