Выбор случайной записи из моделей Django: методы и подходы

Пройдите тест, узнайте какой профессии подходите

Я предпочитаю
0%
Работать самостоятельно и не зависеть от других
Работать в команде и рассчитывать на помощь коллег
Организовывать и контролировать процесс работы

Быстрый ответ

Для получения случайной записи с использованием ORM Django примените метод order_by('?') в связке с .first():

Python
Скопировать код
from myapp.models import MyModel
random_record = MyModel.objects.order_by('?').first()

Теперь random_record содержит случайно извлеченный объект из модели MyModel. Этот метод идеально подходит для небольших наборов данных, но при работе с большим объемом данных рекомендуется применять более эффективные решения.

Кинга Идем в IT: пошаговый план для смены профессии

Как улучшить процесс выборки случайной записи?

Пользовательские менеджеры – путь к эффективности

Использование кастомного менеджера является оправданным при работе с большими таблицами и особенно при использовании MySQL. Данный метод основывается на комбинации aggregate(Count('id')) и randint, что обеспечивает высокую скорость выборки:

Python
Скопировать код
from random import randint
from django.db.models import Manager, Count

class RandomManager(Manager):
    def random(self):
        count = self.aggregate(count=Count('id'))['count']
        random_index = randint(0, count – 1)
        return self.all()[random_index]

Этот менеджер необходимо применить к модели следующим образом:

Python
Скопировать код
class MyModel(models.Model):
    # ...
    
    objects = RandomManager()

Теперь, используя MyModel.objects.random(), вы получите случайный объект.

Обработка сложностей и забота о гапах в ID

Чтобы учесть возможные пропуски в ID, обусловленные удалением записей, метод можно модифицировать таким образом, чтобы он извлекал случайный ID из действующего диапазона ID:

Python
Скопировать код
from django.db.models import Max, Min

class RandomManager(Manager):
    def truly_random(self):
        max_id = self.aggregate(max_id=Max("id"))['max_id']
        if max_id:
            min_id = self.aggregate(min_id=Min("id"))['min_id']
            random_id = randint(min_id, max_id)
            return self.filter(id__gte=random_id).first()

Предварительная фильтрация – проработка эффективности заранее

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

Python
Скопировать код
class ActiveRandomManager(RandomManager):
    def get_queryset(self):
        return super().get_queryset().filter(is_active=True)

Визуализация

Можно сравнить процесс выбора случайной книги с закрытыми глазами на полке с извлечением случайной записи с помощью ORM Django:

Markdown
Скопировать код
Полка с книгами (📚): [Книга 1, Книга 2, Книга 3, ..., Книга N]

Случайную выборку можно запустить так:

Python
Скопировать код
random_book = Book.objects.order_by('?').first()

И теперь у вас в руках случайно выбранная книга.

Настраиваем случайность с помощью пользователями задаваемых методов

Пользовательские менеджеры позволяют создавать специализированные типы выборки для ваших моделей. Например, можно сортировать записи по количеству посещений, чтобы получить наиболее или наименее популярные объекты:

Python
Скопировать код
class MyModelManager(RandomManager):
    def least_visited(self):
        return self.order_by('visit_count').first()
    
    def most_popular(self):
        return self.order_by('-visit_count').first()

Обеспечиваем совместимость

Если вы используете старую версию Django, стоит помнить о совместимости. API запросов Django позволяет поддерживать разработанные методы, одновременно оставаясь совместимым со старыми версиями.

Разрабатываем модель случайного извлечения данных

Если вы только начинаете вникать в работу с пользовательскими менеджерами или методами, RandomManager предлагает базовую конструкцию, которую можно расширить и настроить под конкретные цели вашего проекта.

Полезные материалы