Ответ 1
Насколько это случайным образом? Должен ли он быть другим для каждого пользователя, или это просто внешний вид случайности, который важен?
Если это последний, вы можете просто добавить поле под названием ordering
к рассматриваемой модели и заполнить его случайными целыми числами.
В противном случае, если набор записей не является небольшим (и, если он будет выгружен, я сомневаюсь в этом), то хранение отдельного случайного запроса для каждого сеанса может очень быстро стать проблемой памяти, если вы не знаете, что база пользователей очень мала, Вот одно возможное решение, которое имитирует случайность, но на самом деле создает только 5 случайных множеств:
import random
from django.core import cache
RANDOM_EXPERIENCES=5
def my_view(request):
if not request.session.get('random_exp'):
request.session['random_exp']=random.randrange(0,RANDOM_EXPERIENCES)
object_list = cache.get('random_exp_%d' % request.session['random_exp'])
if not object_list:
object_list = list(Object.objects.all().order_by('?'))
cache.set('random_exp_%d' % request.session['random_exp'], object_list, 100)
paginator = Paginator(object_list, 10)
page = 1 # or whatever page we have
display_list = paginator.page(page)
....
В этом примере вместо создания отдельного набора запросов для каждого пользователя (в результате чего потенциально тысячи запросов в хранилище) и хранения его в request.session(менее эффективный механизм хранения, чем кеш, который может быть настроен на использование чего-то очень эффективно, как memcached), теперь у нас всего 5 запросов, хранящихся в кеше, но, надеюсь, достаточно случайный опыт для большинства пользователей. Если вы хотите больше случайности, это должно помочь увеличить значение для RANDOM_EXPERIENCES. Я думаю, вы могли бы подняться до 100 с небольшим количеством проблем с производительностью.
Если сами записи изменяются нечасто, вы можете установить чрезвычайно высокий тайм-аут для кеша.
Update
Вот способ реализовать его, который использует немного больше памяти/хранилища, но гарантирует, что каждый пользователь может "держаться" за свой запрос без опасности его тайм-аута кэша (если предположить, что 3 часа достаточно для просмотра записей).
import datetime
...
if not request.session.get('random_exp'):
request.session['random_exp']="%d_%d" % (
datetime.datetime.strftime(datetime.datetime.now(),'%Y%m%dH'),
random.randrange(0, RANDOM_EXPERIENCES)
)
object_list = cache.get("random_exp_%s" % request.session['random_exp'])
if not object_list:
object_list = list(Object.objects.all().order_by('?'))
cache.set(cache_key, "random_exp_%s" % request.session['random_exp'], 60*60*4)
Здесь мы создаем кэшированный запрос, который не задерживается на 4 часа. Тем не менее, ключ request.session устанавливается на год, месяц, день и час, так что кто-то, кто приходит, видит текущий набор записей в течение этого часа. Любой, кто уже просмотрел запрос, сможет увидеть его как минимум еще на 3 часа (или до тех пор, пока их сеанс все еще активен) до истечения срока его действия. В лучшем случае будет храниться 5 * RANDOM_EXPERIENCES запросов в кеше.