Django: получить случайный объект из базы данных по id, но если id не существует, попробовать еще раз
Попытка получить случайный объект из базы данных с идентификатором. Некоторые идентификаторы в таблице базы данных отсутствуют, например, 1, 2, 4, 5, 6, 19, 20... поэтому мне нужно убедиться, что я не получу ошибку при попытке получить объект.
Это, кажется, работает. Есть ли лучший способ.
def get_random_title():
title_count = OriginalTitle.objects.count()
random_id = random.randrange(1, title_count)
random_title_obj = None
while random_title_obj is None:
try:
random_title_obj = OriginalTitle.objects.get(id=random_id)
except ObjectDoesNotExist:
continue
return random_title_obj.title
def play(request):
random_title = get_random_title()
context = {
'original_title': random_title
}
return render(request, 'game/game.html', context)
Вы можете использовать random.sample() на объекте QuerySet. или изменить порядок следования строк.
OriginalTitle.objects.order_by('?')[:1]
# edit your get_random_title
def get_random_title():
random_title_obj = OriginalTitle.objects.order_by('?')[0]
return random_title_obj.title
пожалуйста, прочитайте более подробную информацию в этом ответе
Ок. Спасибо за ответы. Я избавился от функции get_random_title() и просто поместил одну строку в представление play()
def play(request):
random_title = OriginalTitle.objects.order_by("?").first().title
context = {
'original_title': random_title
}
return render(request, 'game/game.html', context)
Одно замечание всем, кто использует этот ответ: Теперь я вижу в docs. говорится: "Обратите внимание: запросы order_by('?') могут быть дорогими и медленными, в зависимости от используемой вами базы данных."
Использование .order_by('?') является дорогостоящим . Действительно, как говорится в документации :
Примечание:
order_by('?')запросы могут быть дорогими и медленными, в зависимости от используемого бэкенда базы данных.
Для большинства баз данных он присвоит каждой записи случайное число, а затем упорядочит ее по этому числу, что делает его линейным по размеру таблицы.
Вы можете вернуть образец базы данных с помощью:
def get_random_title():
title_count = OriginalTitle.objects.count()
idx = random.randrange(0, title_count)
random_title_obj = OriginalTitle.objects.all()[idx].title
Это сделает два запроса, но для больших таблиц может превзойти .order_by('?').