Метод distinct

Метод distinct применяется к QuerySet и возвращает новый QuerySet, содержащий только уникальные записи. Он полезен при выполнении запросов, которые могут возвращать дублирующиеся строки из-за соединений с другими таблицами. Метод работает на уровне SQL и добавляет ключевое слово DISTINCT в генерируемый запрос. Без аргументов он удаляет полные дубликаты строк. Также можно передать имена полей, чтобы получить уникальные комбинации значений этих полей.

Синтаксис

pythonModel.objects.distinct()

С указанием полей:

pythonModel.objects.distinct(*fields)

Пример

Рассмотрим модель, в которой хранятся записи о пользователях и их заказах:

pythonfrom django.db import models

class User(models.Model):
  name = models.CharField(max_length=100)
  email = models.EmailField()
  city = models.CharField(max_length=100)

  def __str__(self):
    return self.name

class Order(models.Model):
  user = models.ForeignKey(User, on_delete=models.CASCADE)
  product = models.CharField(max_length=200)
  price = models.DecimalField(max_digits=10, decimal_places=2)
  created_at = models.DateTimeField(auto_now_add=True)

Давайте получим список всех городов, в которых живут пользователи, используя метод distinct для удаления дубликатов:

pythonfrom myapp.models import User

cities = User.objects.values('city').distinct()
for city in cities:
  print(city['city'])

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

python"New York"
"Los Angeles"
"Chicago"
"Houston"

Пример

Получим уникальные комбинации имени пользователя и города, где были сделаны заказы, используя distinct с несколькими полями:

pythonfrom myapp.models import Order

unique_users = Order.objects.values('user__name', 'user__city').distinct('user__name', 'user__city')
for user in unique_users:
  print(f"User: {user['user__name']}, City: {user['user__city']}")

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

python"User: John Doe, City: New York"
"User: Jane Smith, City: Los Angeles"
"User: John Doe, City: Chicago"

Пример

При использовании соединений (joins) метод distinct становится особенно полезным. Получим уникальных пользователей, которые сделали заказы:

pythonfrom myapp.models import User, Order

users_with_orders = User.objects.filter(order__isnull=False).distinct()
for user in users_with_orders:
  print(f"User: {user.name}, Orders: {user.order_set.count()}")

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

python"User: John Doe, Orders: 3"
"User: Jane Smith, Orders: 2"
"User: Bob Johnson, Orders: 1"

Пример

Метод distinct также можно комбинировать с другими методами QuerySet, такими как filter и order_by. Получим уникальные продукты из заказов, сделанных в определенном диапазоне цен:

pythonfrom myapp.models import Order

products = Order.objects.filter(price__range=(50, 200)).values('product').distinct().order_by('product')
for product in products:
  print(product['product'])

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

python"Desk Lamp"
"Office Chair"
"USB Cable"
"Wireless Mouse"

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

  • метод filter,
    который фильтрует записи в QuerySet по заданным условиям
  • метод values,
    который возвращает QuerySet словарей вместо объектов
  • метод order_by,
    который сортирует QuerySet по указанным полям
  • метод annotate,
    который добавляет аннотации к каждому объекту в QuerySet