HämtningslägenLink to this heading

När du använder modellfält som inte lästes in som en del av den ursprungliga frågan hämtar Django fältets data från databasen. Du kan anpassa hur denna hämtning fungerar med ett hämtningsläge, för att göra den mer effektiv eller till och med blockera den.

Använd QuerySet.fetch_mode() för att ange hämtningsläge för modellinstanser som hämtas av en QuerySet:

Python
from django.db import models

books = Book.objects.fetch_mode(models.FETCH_PEERS)

Hämtningslägen gäller för:

Django kopierar hämtningsläget för en instans till alla relaterade objekt som det hämtar, så läget gäller för ett helt relationsträd, inte bara för toppnivåmodellen i den ursprungliga QuerySet. Kopieringen görs också i relationshanterare, även om hämtningslägen inte påverkar dessa hanterares frågor.

Tillgängliga lägenLink to this heading

Django tillhandahåller tre hämtningslägen. Vi förklarar dem nedan med hjälp av dessa modeller:

Python
from django.db import models


class Author(models.Model): ...


class Book(models.Model):
    author = models.ForeignKey(Author, on_delete=models.CASCADE)
    ...

…och den här loopen:

Python
for book in books:
    print(book.author.name)

…där books är en QuerySet med Book-instanser som använder något hämtningsläge.

FETCH_ONELink to this definition

Hämtar det saknade fältet endast för den aktuella instansen. Detta är standardläget.

Om du använder FETCH_ONE för exemplet ovan används:

  • 1 fråga för att hämta books

  • N frågor, där N är antalet böcker, för att hämta det saknade fältet author

…vilket ger totalt 1+N frågor. Detta frågemönster kallas ”N+1-frågeproblemet” eftersom det ofta leder till prestandaproblem när N är stort.

FETCH_PEERSLink to this definition

Hämtar det saknade fältet för den aktuella instansen och dess ”peer”-instanser – instanser som kom från samma ursprungliga QuerySet. Lägets beteende bygger på antagandet att om du behöver ett fält för en instans behöver du förmodligen det för alla instanser i samma grupp, eftersom du troligen kommer att behandla dem på samma sätt.

Om du använder FETCH_PEERS för exemplet ovan används:

  • 1 fråga för att hämta books

  • 1 fråga för att hämta alla saknade fält author för gruppen av böcker

…vilket ger totalt 2 frågor. Gruppfrågan gör det här läget mycket effektivare än FETCH_ONE och liknar ett anrop vid behov till QuerySet.prefetch_related() eller prefetch_related_objects(). Användning av FETCH_PEERS kan med liten ansträngning minska de flesta fall av ”N+1-frågeproblemet” till två frågor.

”Peer”-instanserna spåras i en lista med svaga referenser, för att undvika minnesläckor när vissa peer-instanser kasseras.

FETCH_RAISELink to this definition

Utlöser undantaget FieldFetchBlocked.

Om du använder FETCH_RAISE för exemplet ovan utlöses ett undantag när book.author används, så här:

Python
FieldFetchBlocked("Fetching of Primary.value blocked.")

Detta läge kan förhindra oavsiktliga frågor i prestandakritiska delar av koden.

Gör ett hämtningsläge till standard för en modellklassLink to this heading

Ange standardhämtningsläge för en modellklass med en anpassad hanterare som åsidosätter get_queryset():

Python
from django.db import models


class BookManager(models.Manager):
    def get_queryset(self):
        return super().get_queryset().fetch_mode(models.FETCH_PEERS)


class Book(models.Model):
    title = models.TextField()
    author = models.ForeignKey("Author", on_delete=models.CASCADE)

    objects = BookManager()