Метод distinct
Метод distinct применяется к QuerySet и возвращает
новый QuerySet, содержащий только уникальные записи.
Он полезен при выполнении запросов, которые могут возвращать
дублирующиеся строки из-за соединений с другими таблицами.
Метод работает на уровне SQL и добавляет ключевое слово
DISTINCT в генерируемый запрос. Без аргументов он удаляет
полные дубликаты строк. Также можно передать имена полей,
чтобы получить уникальные комбинации значений этих полей.
Синтаксис
Model.objects.distinct()
С указанием полей:
Model.objects.distinct(*fields)
Пример
Рассмотрим модель, в которой хранятся записи о пользователях и их заказах:
from 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 для удаления дубликатов:
from myapp.models import User
cities = User.objects.values('city').distinct()
for city in cities:
print(city['city'])
Результат выполнения кода:
"New York"
"Los Angeles"
"Chicago"
"Houston"
Пример
Получим уникальные комбинации имени пользователя и города,
где были сделаны заказы, используя distinct с несколькими полями:
from 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']}")
Результат выполнения кода:
"User: John Doe, City: New York"
"User: Jane Smith, City: Los Angeles"
"User: John Doe, City: Chicago"
Пример
При использовании соединений (joins) метод distinct
становится особенно полезным. Получим уникальных пользователей,
которые сделали заказы:
from 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()}")
Результат выполнения кода:
"User: John Doe, Orders: 3"
"User: Jane Smith, Orders: 2"
"User: Bob Johnson, Orders: 1"
Пример
Метод distinct также можно комбинировать с другими
методами QuerySet, такими как filter и order_by.
Получим уникальные продукты из заказов, сделанных в определенном
диапазоне цен:
from 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'])
Результат выполнения кода:
"Desk Lamp"
"Office Chair"
"USB Cable"
"Wireless Mouse"