Le nombre de projets Django dans l'entreprise augmente, et le nombre de requêtes non cool est susceptible d'augmenter, alors laissez une note facilement.
Utilisez prefetch_related car il serait désastreux d'ignorer la requête à chaque fois que vous effectuez une boucle lors de la récupération de la référence inverse de la clé étrangère ou de l'obtention de la destination de référence de plusieurs à plusieurs sans penser à utiliser ORM. L'histoire de la fonte
S'il s'agit d'une clé étrangère normale, vous pouvez la récupérer par la hiérarchie requise avec select_related.
Pour le moment, un tel modèle
from django.db import models
class Campaign(models.Model):
name = models.CharField(max_length=255)
created_at = models.DateTimeField()
class Creative(models.Model):
name = models.CharField(max_length=255, default="")
campaign = models.ForeignKey(Campaign)
created_at = models.DateTimeField()
Si vous souhaitez soustraire Campaign de Creative, vous pouvez utiliser select_related pour rejoindre et récupérer Campaign sans la sélectionner à chaque fois que vous bouclez.
for creative in Creative.objects.all().select_related():
print(creative.campaign)
Utilisez prefetch_related pour extraire la liste des créations de la campagne
for campaign in Campaign.objects.all().prefetch_related("creative_set"):
print(campaign.creative_set.all())
Il semble que toutes les campagnes sont tirées une fois au lieu de rejoindre, et la liste de campaign.id est tirée à l'endroit. Eh bien, c'est mieux que de voler à chaque fois, et dans la plupart des cas, cela ne semble pas être un problème.
À propos, la réduction de la campagne avec la création se fait généralement avec une requête
Campaign.object.filter(creative_set__name="aaa")
Si vous utilisez simplement prefetch_related, vous ne pouvez obtenir que la chose de XXXX_set.all (). Si vous affinez le creative_set, la requête volera chaque fois que vous bouclez, ce qui vous rend très triste.
for campaign in Campaign.objects.all().prefetch_related("creative_set"):
print(campaign.creative_set.filter(name__startswith="hoge"))
Par conséquent, si vous souhaitez affiner la destination de la référence inverse ou de plusieurs à plusieurs en utilisant un filtre, ou si vous souhaitez spécifier l'ordre, utilisez l'objet Prefetch inclus à partir de la 1.7 de Django. Grâce à ce type, je sens que l'ORM de Django s'est beaucoup amélioré.
from django.db import models
from django.db.models import Prefetch
for campaign in Campaign.objects.all().prefetch_related(Prefetch("creative_set", queryset=Creative.objects.filter(name__startswith="hoge").order_by("-created_at"), to_attr="creatives")):
if len(campaign.creatives) > 0:
print(campaign.id, creatives[0].id)
Avec cela, quel que soit le nombre de campagnes que vous avez, vous n'avez qu'à ignorer la requête deux fois.
Lors du réglage d'une requête, je pense que vous utiliserez le Django Shell pour vérifier la requête, c'est donc une bonne idée de jouer avec le logger afin que l'instruction SQL s'affiche lorsque vous frappez la requête avec le shell. Je pense que je joue avec les paramètres de journal si je le fais normalement, mais je suis heureux si je règle le niveau de journalisation de django.db.backends sur DEBUG uniquement lors de l'enquête sur les requêtes.
settings.py
LOGGING = {
'version': 1,
'handlers': {
'console': {
'level': 'DEBUG',
'class': 'logging.StreamHandler',
}
},
'loggers': {
'django.db.backends': {
'level': 'DEBUG',
'handlers': ['console'],
},
}
}
Pour le réglage par vue, il est basique de vérifier la requête à l'aide de django-debug-toolbar.
Recommended Posts