[PYTHON] Lorsque j'ai vérifié la requête générée par Django, elle a été émise en grand nombre

Django:1.10

Lors de la génération d'une requête avec Django, un grand nombre de requêtes seront émises si vous ne l'écrivez pas soigneusement.

Sortie du journal des requêtes

Tout d'abord, écrivez les paramètres de journal dans manage.py pour générer la requête vers la console du serveur.

manage.py


LOGGING = {
    'version': 1,
    'formatters': {
        'all': {
            'format': '%(message)s'
        },
    },
    'handlers': {
        'console': {
            'level': 'DEBUG',
            'class': 'logging.StreamHandler',
            'formatter': 'all',
        },
    },
    'loggers': {
        'django': {
           'handlers': ['console'],
           'level': 'DEBUG',
        },
    },
}

Vérifiez la requête

Exécutons une requête pour obtenir la liste des livres publiés par l'auteur sélectionné qui a été utilisée la dernière fois.

Comment générer une requête à l'aide de l'opérateur IN dans Django http://qiita.com/nakkun/items/86a94e65fe6785325f54

La source


books = Book.objects.filter(author_id__in = form.cleaned_data['author'])

Résultat d'exécution


(0.002) SELECT "books_book"."id", "books_book"."name", "books_book"."author_id" FROM "books_book" WHERE "books_book"."author_id" IN (1, 3); args=(1, 3)

Le SQL fonctionnait comme prévu. J'ai reçu la même requête en utilisant "author_ \ _ id_ \ in" comme indiqué ci-dessous. (Le nombre de "" est différent)

La source


books = Book.objects.filter(author__id__in = form.cleaned_data['author'])

Dans le cas de "author_ \ _ id_ \ _in", je me demandais s'ils allaient rejoindre, mais ce n'était pas le cas.

Un grand nombre de requêtes! ??

Il n'y a pas de problème particulier jusqu'à présent, mais si vous essayez d'afficher le nom de l'auteur après cela, le résultat de l'exécution sera le suivant.

La source


books = Book.objects.filter(author_id__in = form.cleaned_data['author'])
[print(book.author.name) for book in books]

Résultat d'exécution


(0.003) SELECT "books_book"."id", "books_book"."name", "books_book"."author_id" FROM "books_book" WHERE "books_book"."author_id" IN (1, 3); args=(1, 3)
(0.001) SELECT "books_author"."id", "books_author"."name" FROM "books_author" WHERE "books_author"."id" = 1; args=(1,)
Hirotsugu Mori
(0.000) SELECT "books_author"."id", "books_author"."name" FROM "books_author" WHERE "books_author"."id" = 3; args=(3,)
Miyagiya Masamitsu
(0.000) SELECT "books_author"."id", "books_author"."name" FROM "books_author" WHERE "books_author"."id" = 3; args=(3,)
Miyagiya Masamitsu
(0.001) SELECT "books_author"."id", "books_author"."name" FROM "books_author" WHERE "books_author"."id" = 3; args=(3,)
Miyagiya Masamitsu
(0.000) SELECT "books_author"."id", "books_author"."name" FROM "books_author" WHERE "books_author"."id" = 3; args=(3,)
Miyagiya Masamitsu

J'ai émis une requête assez inutile.

Vous devez donc écrire une source qui émettra une requête jointe comme celle-ci:

La source


books = Book.objects.select_related().filter(author_id__in = form.cleaned_data['author'])
[print(book.author.name) for book in books]

Résultat d'exécution


(0.004) SELECT "books_book"."id", "books_book"."name", "books_book"."author_id", "books_author"."id", "books_author"."name" FROM "books_book" INNER JOIN "books_author" ON ("books_book"."author_id" = "books_author"."id") WHERE "books_book"."author_id" IN (1, 3); args=(1, 3)
Hirotsugu Mori
Miyagiya Masamitsu
Miyagiya Masamitsu
Miyagiya Masamitsu
Miyagiya Masamitsu

Maintenant, vous ne devez émettre le SQL qu'une seule fois.

Il peut être préférable de développer en vérifiant le SQL avant de vous y habituer afin de ne pas lancer une grande quantité de SQL sans le savoir.

Supplément

Environ 3 autres méthodes.

① Comment utiliser prefetch_related

La source


books = Book.objects.filter(author_id__in = form.cleaned_data['author']).prefetch_related('author')
[print(book.author.name) for book in books]

Résultat d'exécution


(0.001) SELECT "books_book"."id", "books_book"."name", "books_book"."author_id" FROM "books_book" WHERE "books_book"."author_id" IN (1, 3); args=(1, 3)
(0.001) SELECT "books_author"."id", "books_author"."name" FROM "books_author" WHERE "books_author"."id" IN (1, 3); args=(1, 3)
Hirotsugu Mori
Miyagiya Masamitsu
Miyagiya Masamitsu
Miyagiya Masamitsu
Miyagiya Masamitsu

② À partir du modèle Auteur

La source


authors = Author.objects.filter(id__in = form.cleaned_data['author'])
[[print(book.atuhor.name) for book in author.book_set.all()] for author in authors]

Résultat d'exécution


(0.002) SELECT "books_author"."id", "books_author"."name" FROM "books_author" WHERE "books_author"."id" IN (1, 3); args=(1, 3)
(0.001) SELECT "books_book"."id", "books_book"."name", "books_book"."author_id" FROM "books_book" WHERE "books_book"."author_id" = 1; args=(1,)
Hirotsugu Mori
(0.000) SELECT "books_book"."id", "books_book"."name", "books_book"."author_id" FROM "books_book" WHERE "books_book"."author_id" = 3; args=(3,)
Miyagiya Masamitsu
Miyagiya Masamitsu
Miyagiya Masamitsu
Miyagiya Masamitsu

③ Utilisez prefetch_related à partir du modèle Author

La source


authors = Author.objects.filter(id__in = form.cleaned_data['author']).prefetch_related("book_set")
[[print(book.atuhor.name) for book in author.book_set.all()] for author in authors]

Résultat d'exécution


(0.002) SELECT "books_author"."id", "books_author"."name" FROM "books_author" WHERE "books_author"."id" IN (1, 3); args=(1, 3)
(0.002) SELECT "books_book"."id", "books_book"."name", "books_book"."author_id" FROM "books_book" WHERE "books_book"."author_id" IN (1, 3); args=(1, 3)
Hirotsugu Mori
Miyagiya Masamitsu
Miyagiya Masamitsu
Miyagiya Masamitsu
Miyagiya Masamitsu

Recommended Posts

Lorsque j'ai vérifié la requête générée par Django, elle a été émise en grand nombre
django geodjango auquel j'ai fait référence quand je suis resté coincé dans le tutoriel (édition)
Ce que j'ai fait quand j'étais en colère de le mettre avec l'option enable-shared
Je pensais ne pas avoir vu le fichier pyc récemment, mais il a été isolé dans pycache par python3
Où est l'emplacement levé dans la trace de pile d'exceptions? Où a-t-il été généré?
Récupérer la chaîne de requête (chaîne de requête) avec Django
Lorsque j'ai essayé d'exécuter Python, j'ai été ignoré dans le Microsoft Store
Django ~ Affichons-le sur le navigateur ~
Dans IPython, quand j'ai essayé de voir la valeur, c'était un générateur, donc je l'ai inventé quand j'étais frustré.
[Python] Précautions lors de l'acquisition de données en grattant et en les mettant dans la liste
J'ai vérifié si l'API COTOHA pouvait comprendre Mansai, et c'était raisonnable.
La fonction _authenticate_with_backend était obsolète dans django auth.autenticate
Quand j'essaye matplotlib en Python, il dit 'cairo.Context'
J'ai vérifié la période de rétention de session de django
J'ai vérifié le calendrier supprimé dans le calendrier de l'Avent Qiita 2016
J'ai vérifié la vitesse de référence lors de l'utilisation de la liste python, du dictionnaire et du type de jeu.
Il est devenu TLE lorsque j'ai confirmé l'opération avec la fonction d'impression dans la compétition pro
Le nom de fichier enregistré par pysheng était un nombre hexadécimal, donc je l'ai corrigé.
J'ai essayé de faire sonner le téléphone lorsqu'il a été publié sur le poste IoT
Lorsque j'explore la webapi qui apparaît pendant le rendu, elle a été lue avec CORS
Python: peut être répété en lambda
Ce que j'ai appris en participant aux qualifications ISUCON10
Quand j'ai essayé le concours AtCoder pour débutants, c'était un résultat terrible, alors je regarde en arrière
Une histoire à laquelle j'étais accro en spécifiant nil comme argument de fonction dans Go