[PYTHON] Utilisez prefetch_related commodément avec Django

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.

Utiliser normalement

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")

Utiliser l'objet Prefetch

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.

Afficher la requête

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

Utilisez prefetch_related commodément avec Django
Utiliser Gentelella avec Django
Utilisez LESS avec Django
Utiliser MySQL avec Django
[Django] Utiliser MessagePack avec le framework Django REST
Utiliser les pictogrammes Unicode 6.0 avec django / MySQL
Internationalisation avec Django
CRUD avec Django
Utilisez le conteneur de développement Docker facilement avec VS Code
Utilisez Python / Django avec Windows Azure Cloud Service!
Authentifier Google avec Django
Django 1.11 a démarré avec Python3.6
Télécharger des fichiers avec Django
Utilisez mecab-ipadic-neologd avec igo-python
Résumé du développement avec Django
Utiliser ansible avec cygwin
Utiliser pipdeptree avec virtualenv
Sortie PDF avec Django
[Python] Utiliser JSON avec Python
Utilisez Mock avec pytest
Sortie Markdown avec Django
Utiliser l'indicateur avec pd.merge
Utiliser mecab avec Python 3
Utiliser tensorboard avec Chainer
Utiliser DynamoDB avec Python
Utiliser pip avec MSYS2
Premiers pas avec Django 1
Envoyer des e-mails avec Django
Utilisez Python 3.8 avec Anaconda
Utiliser les droits d'auteur avec Spacemacs
Téléchargement de fichiers avec django
Utiliser python avec docker
Utiliser TypeScript avec django-compresseur
La mutualisation mécanise avec Django
Utiliser Enum avec SQLAlchemy
Utiliser tensorboard avec NNabla
Utiliser le GPS avec Edison
Django à partir d'aujourd'hui
Premiers pas avec Django 2
Utilisez nim avec Jupyter
Faites Django avec CodeStar (Python3.6.8, Django2.2.9)
Utiliser l'API Trello avec python
Utiliser la mémoire partagée avec une bibliothèque partagée
Utiliser des balises personnalisées avec PyYAML
Utiliser des graphiques directionnels avec networkx
Lancez-vous avec Django! ~ Tutoriel ⑤ ~
Utiliser TensorFlow avec Intellij IDEA
C'était trop facile d'utiliser une base de données existante avec Django
Environnement de site Web de configuration minimale avec django
Créer une API avec Django
Utiliser l'API Twitter avec Python
Utiliser pip avec Jupyter Notebook
Faites Django avec CodeStar (Python3.8, Django2.1.15)
Déployer Django sans serveur avec Lambda
Python3 + Django ~ Mac ~ avec Apache
Utiliser DATE_FORMAT avec le filtre SQLAlchemy
Utiliser TUN / TAP avec Python
Premiers pas avec Python Django (1)
Créer une page d'accueil avec django
Premiers pas avec Python Django (4)
Créer une application Web avec Django