Как выполняется сортировка данных в Django ORM?

Ответ

В Django ORM для сортировки результатов запроса используется метод order_by() у объекта QuerySet. Этот метод транслируется в SQL-выражение ORDER BY и позволяет упорядочивать данные по одному или нескольким полям.

Основные способы использования order_by():

  1. Сортировка по одному полю (по возрастанию): Укажите имя поля в качестве аргумента.

    # Сортировка пользователей по имени (от А до Я)
    users = User.objects.order_by('username')
  2. Сортировка по одному полю (по убыванию): Добавьте минус (-) перед именем поля.

    # Сортировка статей по дате создания (от новых к старым)
    articles = Article.objects.order_by('-created_at')
  3. Сортировка по нескольким полям: Передайте несколько имен полей в order_by(). Сортировка будет выполняться последовательно.

    # Сортировка товаров сначала по категории (возрастание), затем по цене (убывание)
    products = Product.objects.order_by('category', '-price')
  4. Сортировка по связанным полям (JOIN): Используйте синтаксис __ для доступа к полям связанных моделей.

    # Сортировка комментариев по имени автора
    comments = Comment.objects.order_by('author__username')

Сортировка по умолчанию в модели:

Вы можете определить порядок сортировки по умолчанию для модели, используя опцию ordering во вложенном классе Meta модели. Это будет применяться ко всем QuerySet, если явно не переопределено.

from django.db import models

class Post(models.Model):
    title = models.CharField(max_length=200)
    published_date = models.DateTimeField(auto_now_add=True)

    class Meta:
        # Сортировка по умолчанию: от новых постов к старым
        ordering = ['-published_date', 'title']

# Теперь Post.objects.all() будет отсортирован по published_date DESC, затем по title ASC
posts = Post.objects.all()

Отмена сортировки:

Чтобы отменить любую предыдущую сортировку (включая сортировку по умолчанию из Meta.ordering), вызовите order_by() без аргументов или с None.

# Отменяет любую сортировку и возвращает QuerySet без определенного порядка
queryset = MyModel.objects.order_by()
# Или
queryset = MyModel.objects.order_by(None)