Метод difference
Метод difference применяется к QuerySet и возвращает
новый QuerySet, содержащий объекты, которые есть в первом
наборе, но отсутствуют во втором. Этот метод доступен только
для наборов запросов, работающих с одной и той же моделью.
Результатом является новый QuerySet, содержащий объекты,
которые принадлежат первому набору, но не принадлежат
второму. Метод используется для выполнения операции разности
множеств на уровне базы данных.
Синтаксис
first_queryset.difference(second_queryset)
Где first_queryset и second_queryset - это
два QuerySet, принадлежащих одной модели. Метод возвращает
новый QuerySet, который содержит объекты из первого набора,
отсутствующие во втором.
Пример . С одной моделью
Пусть у нас есть модель Article с полями title и status.
Получим статьи со статусом "draft", которые не являются
статьями пользователя с id=1:
from myapp.models import Article
draft_articles = Article.objects.filter(status='draft')
user_articles = Article.objects.filter(author_id=1)
res = draft_articles.difference(user_articles)
for article in res:
print(article.title)
Результат выполнения кода:
"Draft article 3"
"Draft article 5"
Пример . С цепочкой методов
Метод difference можно комбинировать с другими
методами QuerySet. Например, получим последние 10 статей,
которые не были опубликованы в текущем году:
from myapp.models import Article
from datetime import date
recent_articles = Article.objects.order_by('-created_at')[:10]
this_year_articles = Article.objects.filter(
created_at__year=date.today().year
)
res = recent_articles.difference(this_year_articles)
print(f"Count: {res.count()}")
for article in res:
print(article.title)
Результат выполнения кода:
"Count: 3"
"Article from last year"
"Article from last year 2"
"Article from last year 3"
Пример . С ManyToManyField
Пусть у нас есть модель Category, связанная с
моделью Article через ManyToManyField.
Найдем категории, в которых есть статьи, но нет статей
со статусом "archived":
from myapp.models import Category, Article
categories_with_articles = Category.objects.filter(
article__isnull=False
).distinct()
categories_with_archived = Category.objects.filter(
article__status='archived'
).distinct()
res = categories_with_articles.difference(
categories_with_archived
)
for category in res:
print(category.name)
Результат выполнения кода:
"News"
"Tech"
Смотрите также
-
метод
union,
который выполняет объединениеQuerySet -
метод
intersection,
который возвращает пересечениеQuerySet -
метод
filter,
который фильтруетQuerySetпо заданным условиям -
метод
exclude,
который исключает записи изQuerySet