Метод difference

Метод difference применяется к QuerySet и возвращает новый QuerySet, содержащий объекты, которые есть в первом наборе, но отсутствуют во втором. Этот метод доступен только для наборов запросов, работающих с одной и той же моделью. Результатом является новый QuerySet, содержащий объекты, которые принадлежат первому набору, но не принадлежат второму. Метод используется для выполнения операции разности множеств на уровне базы данных.

Синтаксис

pythonfirst_queryset.difference(second_queryset)

Где first_queryset и second_queryset - это два QuerySet, принадлежащих одной модели. Метод возвращает новый QuerySet, который содержит объекты из первого набора, отсутствующие во втором.

Пример . С одной моделью

Пусть у нас есть модель Article с полями title и status. Получим статьи со статусом "draft", которые не являются статьями пользователя с id=1:

pythonfrom 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)

Результат выполнения кода:

python"Draft article 3"
"Draft article 5"

Пример . С цепочкой методов

Метод difference можно комбинировать с другими методами QuerySet. Например, получим последние 10 статей, которые не были опубликованы в текущем году:

pythonfrom 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)

Результат выполнения кода:

python"Count: 3"
"Article from last year"
"Article from last year 2"
"Article from last year 3"

Пример . С ManyToManyField

Пусть у нас есть модель Category, связанная с моделью Article через ManyToManyField. Найдем категории, в которых есть статьи, но нет статей со статусом "archived":

pythonfrom 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)

Результат выполнения кода:

python"News"
"Tech"

Смотрите также

  • метод union,
    который выполняет объединение QuerySet
  • метод intersection,
    который возвращает пересечение QuerySet
  • метод filter,
    который фильтрует QuerySet по заданным условиям
  • метод exclude,
    который исключает записи из QuerySet