如何有一个“随机"在 Django 中使用分页对一组对象进行排序? [英] How to have a "random" order on a set of objects with paging in Django?

查看:28
本文介绍了如何有一个“随机"在 Django 中使用分页对一组对象进行排序?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个包含 100 个左右条目的模型 - 客户希望这些条目以随机"顺序出现,但也希望在其中进行分页.

I have a model with 100 or so entries - the client would like these entries to appear in a 'random' order, but would also like paging in there.

def my_view(request):
  object_list = Object.objects.all().order_by('?')
  paginator = Paginator(object_list, 10)
  page = 1 # or whatever page we have
  display_list = paginator.page(page)
  ....

所以我的问题应该是 - 如何让我的 object_list 在每个用户会话中创建一次?

So my question should really be - how can I have my object_list created once per user session?

推荐答案

这些随机数到底有多随机?是否必须对每个用户都不同,还是仅仅是重要的外观随机性?

Exactly how random must these be? Does it have to be different for each user, or is it merely the appearance of randomness that is important?

如果是后者,那么您可以简单地向相关模型添加一个名为 ordering 的字段,并用随机整数填充它.

If it is the latter, then you can simply add a field called ordering to the model in question, and populate it with random integers.

否则,除非记录集很小(而且,鉴于它正在被分页,我对此表示怀疑),否则为每个会话存储一个单独的随机查询集可能会很快成为内存问题,除非您知道用户群非常小.这是一种模拟随机性但实际上仅创建 5 个随机集的可能解决方案:

Otherwise, unless the recordset is small (and, given it is being paged, I doubt it), then storing a separate random queryset for each session could become a memory issue very quickly unless you know that the user base is very small. Here is one possible solution that mimics randomness but in reality creates only 5 random sets:

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.

In this example, instead of creating a separate queryset for each user (resulting in potentially thousands of querysets in storage) and storing it in request.session (a less efficient storage mechanism than cache, which can be set to use something very efficient indeed, like memcached), we now have just 5 querysets stored in cache, but hopefully a sufficiently random experience for most users. If you want more randomness, increasing the value for RANDOM_EXPERIENCES should help. I think you could probably go up as high as 100 with few perfomance issues.

如果记录本身不经常更改,您可以为缓存设置一个极高的超时时间.

If the records themselves change infrequently, you can set an extremely high timeout for the cache.

这是一种实现它的方法,它使用稍微更多的内存/存储,但确保每个用户都可以坚持"他们的查询集而不会出现缓存超时的危险(假设 3 小时足以查看记录).

Here's a way to implement it that uses slightly more memory/storage but ensures that each user can "hold on" to their queryset without danger of its cache timing out (assuming that 3 hours is long enough to look at the records).

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 个查询集.

Here we create a cached queryset that does not time out for 4 hours. However, the request.session key is set to the year, month, day, and hour so that someone coming in sees a recordset current for that hour. Anyone who has already viewed the queryset will be able to see it for at least another 3 hours (or for as long as their session is still active) before it expires. At most, there will be 5*RANDOM_EXPERIENCES querysets stored in cache.

这篇关于如何有一个“随机"在 Django 中使用分页对一组对象进行排序?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆