Ленивые запросы к базе данных

Когда вы пишете запрос на чтение в Django, на самом деле, он не исполняется сразу же. Звучит странно, но строчка Post.objects.all() не шлёт никакие запросы в БД. Запросы в Django ORM ленивые и они не отправляются до тех пор, пока их не запустят (в англоязычных текстах это называют evaluate).

В этой статье мы воспользуемся моделью Post в блоге. У него есть заголовок и текст:

class Post(models.Model):
    title = models.CharField(max_length=200)
    text = models.TextField()

Обратите внимание, что запросы на создание или удаление запускаются сразу:

created_post = Post.objects.create(title="Новый пост", text="Текст нового поста")
created_post.delete()

Но если это запрос на чтение, то сколько бы вы ни уточняли запрос, он не запустится и не пойдёт в БД:

posts = Post.objects.all()
posts_by_alphabet = posts.order_by("title")
posts_about_harry_potter = Post.objects.filter(title__icontains="Гарри Поттер")

Все эти строчки ничего не делают в БД, пока вы не попытаетесь ими воспользоваться:

for post in posts_by_alphabet:
    print(post.title)

Как посмотреть когда запрос запустился

Это можно посмотреть в Django Debug Toolbar. Он показывает на каких строчках какие запросы запустились. Вот статья как им пользоваться.

Примеры кода, которые запускают запрос

В документации перечислены все способы, мы перечислим только несколько частых примеров:

  • Итерация в цикле:
    posts = Post.objects.all()
    for post in posts:
        ...
    
  • Получение одной записи
    post = Post.objects.get(id=1)
    
  • Превращение Queryset в список через list()
    posts = list(Post.objects.all())
    
  • Вызов len()
    posts_amount = len(Post.objects.all())
    

    Не делайте так, используйте .count()


Попробуйте бесплатные уроки по Python

Получите крутое код-ревью от практикующих программистов с разбором ошибок и рекомендациями, на что обратить внимание — бесплатно.

Переходите на страницу учебных модулей «Девмана» и выбирайте тему.