Сегодня мы переходим к следующей важной части — QuerySet. Это наш способ взаимодействия с данными, но не просто взаимодействия, а такого, которое делает вас мастером управления данными. Пристегнитесь, сегодня будет магия (в её Python-варианте, конечно)!
1. Понятие QuerySet в Django ORM
QuerySet — это основа работы с базой данных в Django. Это, по сути, "набор запросов", который позволяет вам получить доступ к данным, хранящимся в вашей базе. В более простых терминах, QuerySet — это способ сказать Django: "Эй, принеси мне эти записи, а теперь вот эти, а теперь ещё отсортируй их".
Всё взаимодействие с базой данных через Django ORM (Object-Relational Mapping) строится именно на QuerySet. Напоминает поисковый фильтр на сайте интернет-магазина: вы выбираете только нужные параметры (например, "красные кроссовки до 500 у.е."), а QuerySet приносит вам ровно то, что вы запросили.
# Пример работы с QuerySet
from myapp.models import Product
# Получаем все записи из модели Product
products = Product.objects.all()
print(products)
В данном примере objects.all() возвращает QuerySet, содержащий все записи модели Product.
2. Преимущества использования QuerySet
Ленивая загрузка данных
Самая мощная сторона QuerySet — это ленивость. Да-да, не удивляйтесь, лень в программировании иногда бывает добродетелью. QuerySet выполняет реальные SQL-запросы к базе данных только тогда, когда это действительно необходимо. Это позволяет избегать избыточной нагрузки на базу, сокращая количество запросов.
Пример ленивой загрузки:
products = Product.objects.all() # Запрос к базе ещё не отправился
for product in products: # Только здесь выполнится SQL-запрос
print(product.name)
Возможность выполнения сложных SQL-запросов
С помощью QuerySet можно составлять сложные SQL-запросы, не зная SQL. Django заботится о том, чтобы SQL-запросы были эффективными и защищёнными от инъекций. Например, вы можете фильтровать, сортировать и соединять данные в несколько строк Python-кода.
# Фильтруем все продукты, у которых цена меньше 5000
cheap_products = Product.objects.filter(price__lt=5000)
# Сортируем по имени
sorted_products = Product.objects.order_by('name')
3. Основные методы QuerySet
Давайте рассмотрим популярные методы QuerySet, которые вам придётся использовать буквально каждый день:
| Метод | Описание |
|---|---|
all() |
Возвращает все записи модели |
filter(**kwargs) |
Возвращает записи, соответствующие указанным условиям фильтрации |
exclude(**kwargs) |
Возвращает записи, НЕ соответствующие указанным условиям фильтрации |
get(**kwargs) |
Возвращает одну запись, соответствующую условиям (если записей нет или больше одной — будет ошибка) |
order_by(*fields) |
Сортирует записи по указанным полям |
count() |
Возвращает количество записей в QuerySet |
first() и last()QuerySet |
Возвращают первую или последнюю запись в сортированном |
values(*fields) |
Возвращает записи в виде словарей с указанными полями |
distinct() |
Убирает дублирующиеся записи (аналог DISTINCT в SQL) |
Примеры работы с QuerySet
Пример 1. Получаем все записи
products = Product.objects.all()
for product in products:
print(product.name) # Здесь мы выводим имена всех продуктов
Запрос all() возвращает все записи из таблицы Product. Но будьте осторожны: если у вас в базе миллион записей, это может "убить" ваш сервер (ну, почти). Поэтому старайтесь использовать фильтрацию.
Пример 2. Фильтрация данных
from datetime import datetime
# Фильтруем продукты, добавленные в этом месяце
current_month = datetime.now().month
recent_products = Product.objects.filter(created_at__month=current_month)
Здесь мы используем магию фильтрации: __month позволяет выбрать все записи, созданные в текущем месяце. QuerySet поддерживает множество подобных "операторов".
Пример 3. Работа с одним объектом
# Получаем конкретный продукт по id
product = Product.objects.get(id=1)
print(product.name)
get() используется для получения ровно одной записи. Если записи не существует — Django выбросит исключение DoesNotExist. Если записей больше одной — будет ошибка MultipleObjectsReturned.
Пример 4. Сортировка
# Сортируем продукты по цене (по возрастанию)
sorted_products = Product.objects.order_by('price')
# Сортируем продукты по цене (по убыванию)
sorted_products_desc = Product.objects.order_by('-price')
Заметьте, что для сортировки по убыванию используется знак минуса -.
Пример 5. Ограничение выборки
# Получаем только первые 5 записей
first_five = Product.objects.all()[:5]
Как и в SQL, вы можете ограничить количество записей с помощью "срезов".
Тайные силы QuerySet: ленивая загрузка
QuerySet выполняет SQL-запросы "лениво". Это значит, что пока вы не попытаетесь получить данные из QuerySet, никакого запроса в базу не будет. Рассмотрим пример:
products = Product.objects.filter(price__lt=5000)
print(products) # Запроса в базу нет, увидите что-то вроде: <QuerySet []>
print(list(products)) # Только здесь запрос действительно выполнится
Такой подход позволяет вам комбинировать цепочки операций (например, фильтрацию и сортировку) без выполнения промежуточных запросов.
Типичные ошибки при работе с QuerySet
При работе с QuerySet можно наткнуться на несколько распространённых ошибок:
Ошибка при использовании
get(): Если запрос возвращает больше одной записи, вы получите исключениеMultipleObjectsReturned. Используйтеfilter()в случаях, когда вы не уверены в количестве записей.Забудете про ленивую загрузку: Если вы не вызываете методы, которые "вытаскивают" данные, вы можете не увидеть изменений или результатов.
Неправильные фильтры: Используйте точные операторы фильтрации. Например, для строковых полей используйте
__contains,__iexact,__startswith.
Практическое задание
Создайте модель Book с полями title, author, published_date, и выполните следующие действия:
- Получите все книги.
- Отфильтруйте книги, опубликованные после 2020 года.
- Найдите книгу с конкретным названием.
- Отсортируйте книги по дате публикации.
- Выведите только первые 3 книги из базы.
Попробуйте выполнить это в Django Shell, используя команды вроде: python manage.py shell.
Теперь вы знаете, что такое QuerySet, насколько он ленив и как с ним работать. В следующей лекции мы узнаем, как создавать объекты в базе через модели. До встречи! 👋
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ