QuerySet Справочник по API django python

Для эффективной работы с данными в Django, знание работы с QuerySet абсолютно необходимо.
Этот справочник предоставляет практические рекомендации по использованию QuerySet для получения, фильтрации и модификации данных в вашей базе данных. Вы научитесь использовать мощные возможности QuerySet для написания эффективного и лаконичного кода.
Пример: Получение всех пользователей, чьё имя начинается с 'А':
from myapp.models import User
users = User.objects.filter(name__startswith='А')
Обратите внимание на синтаксис. В этом примере используется метод filter(), а также специальная нотация __startswith
для поиска по началу строки. Это всего лишь один из множества мощных методов QuerySet. Используйте QuerySet для фильтрации данных, сортировки, агрегации, получения связанных данных и т.д.
Другой пример: Получение 10 последних созданных объектов.
objects = MyModel.objects.all().order_by('-created_at')[:10]
Здесь мы используем метод order_by()
для сортировки по полю created_at
в обратном порядке и [:10]
для ограничения результата до первых 10 элементов.
QuerySet Справочник по API Django Python
get()
- возвращает единственный объект, соответствующий запросу. Если объектов несколько, вызовет MultipleObjectsReturned
. Используйте для получения единственного конкретного объекта из базы данных.
filter()
- возвращает все объекты, удовлетворяющие заданным критериям. Строит сложные запросы с различными операторами (__exact
, __iexact
, __gt
, __lt
, __contains
, __in
и пр.). Ключевое для оптимизации - корректные условия.
exclude()
- возвращает объекты, которые НЕ соответствуют заданным критериям. Эффективно используется в сочетании с filter()
для составления сложных условий.
all()
- возвращает все объекты модели. Используется, когда нужно получить всю коллекцию.
first()
- возвращает первый объект QuerySet. Эквивалент list(qs)[0]
, но намного эффективнее.
last()
- возвращает последний объект QuerySet.
count()
- возвращает количество объектов в QuerySet. Избегайте len(qs)
, так как это вызовет полное наполнение списка, что менее эффективно.
exists()
- возвращает True
, если QuerySet содержит хоть один объект, False
иначе. Полезно для проверок.
order_by()
- сортирует объекты по заданным полям. Важно для упорядочивания результатов.
values()
и values_list()
- возвращают только указанные поля, а не весь объект, что экономит ресурсы. Используйте values_list()
, если нужно получить только список значений.
distinct()
- удаляет дубликаты из QuerySet. Важно для работы с уникальными записями.
annotate()
- добавляет новые поля в QuerySet, например, используя агрегации (Count
, Sum
, Avg
, Max
, Min
).
reverse()
- изменяет порядок объектов в QuerySet на противоположный.
Пример использования filter()
и exclude()
:
items = Item.objects.filter(price__gt=10).exclude(category='Electronics')
Создание и использование базовых запросов
Для работы с данными в Django используйте QuerySet. Ниже примеры обхода и фильтрации.
Пример 1: Получение всех объектов модели
from your_app.models import YourModel
objects = YourModel.objects.all()
for obj in objects: print(obj.name, obj.age)
Пример 2: Фильтрация объектов
filtered_objects = YourModel.objects.filter(age__gt=20)
(все объекты старше 20)filtered_objects = YourModel.objects.filter(name__icontains='John')
(все объекты, в имени которых содержится "John")filtered_objects = YourModel.objects.filter(name__startswith="A")
(все объекты, имена которых начинаются на "A")filtered_objects = YourModel.objects.filter(is_active=True)
(все активные объекты)filtered_objects = YourModel.objects.exclude(name='Pete')
(все объекты, кроме тех, где имя "Pete")filtered_objects = YourModel.objects.filter(city='London').filter(country='UK')
(сложные условия)
Пример 3: Сортировка объектов
sorted_objects = YourModel.objects.all().order_by('name')
(сортировка по имени в алфавитном порядке)sorted_objects = YourModel.objects.all().order_by('-age')
(сортировка по возрасту, по убыванию)
Пример 4: Прямой доступ к атрибутам модели
age_list = [obj.age for obj in YourModel.objects.all()]
Важно! Замените your_app
и YourModel
соответствующими именами Ваших приложений и моделей.
Для более сложных запросов комбинируйте методы фильтрации, сортировки и выберите нужные поля для возвращения. Всегда уточняйте названия полей и правил в вашей модели.
Работа с логическими операторами в запросах
Для объединения нескольких условий в запросах Django QuerySet используйте логические операторы &
(AND), |
(OR), и ~
(NOT).
- AND (
&
): Объединяет условия, выполняя запрос, только если все они истинны. - OR (
|
): Объединяет условия, выполняя запрос, если хотя бы одно из них истинно. - NOT (
~
): Обращает результат условия, выполняя запрос, только если условие ложно.
Пример AND:
from django.db.models import Q
Author.objects.filter(Q(name='John') & Q(age__gt=30))
Находит авторов с именем 'John' и возрастом больше 30.
Пример OR:
from django.db.models import Q
Author.objects.filter(Q(name='John') | Q(name='Jane'))
Находит авторов с именем 'John' или 'Jane'.
Пример NOT:
from django.db.models import Q
Author.objects.filter(~Q(age__gt=25))
Находит авторов, возраст которых не больше 25. Обратите внимание, что ~Q(x) - это то же что и Q(~x).
Комбинирование операторов:
Сочетайте разные логические операторы для сложных запросов:
from django.db.models import Q
Author.objects.filter(Q(name='John') & (Q(age__gt=30) | Q(country='USA')))
Этот запрос найдёт всех авторов по имени 'John', возраст которых больше 30 или которые живут в США.
- Используйте скобки для ясности и приоритета операций.
- Замените примеры на свои поля, а также используйте другие фильтры.
- Не забудьте, что оператор NOT (
~
) действует на все последующие выражения. Используйте скобки, чтобы оградить от нежелательных эффектов.
Важно: Операторы &
, |
, и ~
применимы к выражениям Q для создания сложных условий.
Фильтрация и выборка по полям
Для фильтрации объектов QuerySet используйте условия в методе filter()
. Пример: MyModel.objects.filter(name='John Doe')
. Это вернёт все объекты модели MyModel
, где поле name
равно 'John Doe'.
filter()
поддерживает логические операторы:
__exact
(равно):MyModel.objects.filter(age__exact=30)
__iexact
(равно, игнорирует регистр):MyModel.objects.filter(name__iexact='jOhN')
__gt
(больше):MyModel.objects.filter(price__gt=100)
__gte
(больше или равно):MyModel.objects.filter(rating__gte=4.5)
__lt
(меньше):MyModel.objects.filter(quantity__lt=5)
__lte
(меньше или равно):MyModel.objects.filter(views__lte=200)
__in
(входит в список):MyModel.objects.filter(category__in=['Books','Electronics'])
__contains
(содержит):MyModel.objects.filter(description__contains='Python')
__icontains
(содержит, игнорирует регистр):MyModel.objects.filter(description__icontains="python")
__startswith
(начинается с):MyModel.objects.filter(title__startswith='The')
__istartswith
(начинается с, игнорирует регистр):MyModel.objects.filter(author__istartswith='J')
__endswith
(заканчивается на):MyModel.objects.filter(filename__endswith='.txt')
Комбинируйте условия: MyModel.objects.filter(age__gt=18, city__exact='London')
. Это даёт все объекты старше 18 лет, проживающих в Лондоне.
Используйте exclude()
для исключения объектов, соответствующих условию: MyModel.objects.exclude(is_active=False)
.
Для выборки определённых полей, используйте values()
или values_list()
. Например, MyModel.objects.values('name','age')
даёт значения только этих полей. MyModel.objects.values_list('name','age',flat = True)
даст плоский список.
Создание и использование агрегаций
Для получения сводных статистических данных используйте агрегации. Ниже примеры создания и использования.
Функция | Описание | Пример |
---|---|---|
Count |
Подсчет количества объектов. | objects.aggregate(total_count=Count('id')) |
Sum |
Суммирование числового поля. | objects.aggregate(total_price=Sum('price')) |
Avg |
Вычисление среднего значения. | objects.aggregate(average_age=Avg('age')) |
Max |
Нахождение максимального значения. | objects.aggregate(max_value=Max('value')) |
Min |
Нахождение минимального значения. | objects.aggregate(min_value=Min('value')) |
Sum без группировки по отдельным значениям |
Подсчет общего количества всех объектов | objects.aggregate(total_count=Count('id')) (аналогично Count) |
Важное замечание: для использования функций `Count`, `Sum`, `Avg` и т.д., используйте метод .aggregate()
.
Пример использования агрегации в запросе:
from django.db.models import Count, Sum products = Product.objects.values('category').annotate(total_products=Count('id')).values('category', 'total_products') print(list(products))
Этот код посчитает общее количество продуктов в каждой категории.
Оптимизация запросов QuerySet
Используйте select_related()
и prefetch_related()
для загрузки связанных данных в один запрос. Например, для получения пользователя и его профиля:
User.objects.select_related('profile').get(pk=1)
User.objects.prefetch_related('profile_image').filter(is_active=True)
Избегайте неявных запросов, создаваемых агрегатными функциями, такими как Count
или Sum
. Используйте annotate()
с конкретными полями, для получения необходимой информации.
Пример использования annotate()
:
Post.objects.annotate(comment_count=Count('comments')).filter(comment_count__gt=5)
Фильтры должны быть явными и релевантными, избегайте ненужной переборки данных.
Пример:
Правильно: Product.objects.filter(category__id=10)
Неправильно: Product.objects.filter(category__in=Category.objects.all())
.
Для сложных запросов, используйте extra()
, raw()
с осторожностью, и всегда контролируйте SQL, который генерируется.
Оптимизируйте запросы с помощью индексов. Убедитесь, что у полей, которые используются в фильтре, есть соответствующие индексы.
Пример добавления индекса:
ALTER TABLE product ADD KEY INDEX (price);
Не забывайте о кэшировании QuerySet-ов, если они часто используются.
Работа с связанными моделями
Для работы с связанными моделями используйте метод prefetch_related()
. Он загружает связанные объекты в одну базу данных, а не отдельные запросы, что значительно повышает эффективность.
Пример:
Представьте модели Author
и Book
, где один автор может иметь несколько книг. Чтобы получить автора и все его книги в одном запросе:
from django.db.models import Prefetch
authors = Author.objects.prefetch_related('books').all()
for author in authors:
print(author.name)
for book in author.books.all():
print(f" - {book.title}")
Этим кодом достигается оптимальная производительность. Если вы используете только Author.objects.all()
, то Django запрашивает всех авторов, а затем для каждого автора производит дополнительный запрос, чтобы получить все его книги, существенно увеличивая загрузку базы.
Альтернативный метод: Если вам нужны только определённые поля из связанной модели, то можно использовать select_related()
. Он эффективнее для запросов с небольшим количеством связанных полей.
authors = Author.objects.select_related('books').all()
select_related()
загрузит только связанное поле books
внутри каждого объекта Author
. Но, если нужно получить все поля из модели Book
, лучше применять prefetch_related()
. Это обеспечивает более производительную загрузку, особенно при большом количестве связанных объектов.