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

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

问题描述

我有一个具有100个左右的条目的模型 - 客户端希望这些条目以随机的顺序显示,但也希望在其中进行分页。

  def my_view(request):
object_list = Object.objects.all()。order_by('?')
paginator = Paginator(object_list,10)
page = 1#或任何页面我们有
display_list = paginator.page(页)
....

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

解决方案

这些都是随机的吗?对于每个用户来说,它必须是不同的,还是仅仅是重要的随机性的外观



如果是后者,那么您可以简单地将一个名为的字段添加到有问题的模型中,并使用随机整数填充。



否则,除非记录集很小(并且由于正在被分页,我怀疑它),那么为每个会话存储一个单独的随机查询集可能会非常快地成为内存问题,除非您知道用户数量非常少。这是一种模拟随机性的可能解决方案,但实际上只创建了5个随机集:

 从django导入随机
。核心导入缓存
RANDOM_EXPERIENCES = 5

def my_view(request):
如果没有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'])
如果不是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#或者我们有
的任何页面display_list = paginator.page(页)
....

在此示例中,不是为每个用户创建一个单独的查询集(导致存储中可能存在数千个查询器)并将其存储在请求中uest.session(比缓存效率更低的存储机制,可以设置为使用非常有效的东西,如memcached),我们现在只有5个查询存储在缓存中,但希望大多数用户有足够的随机体验。如果你想要更多的随机性,增加RANDOM_EXPERIENCES的值应该有帮助。我想你可能会高达100,几乎没有性能问题。



如果记录本身不经常更改,您可以设置超高速缓存的超时值。 / p>

更新



这是一种实现它的方法,它使用更多的内存/存储,但确保每个用户可以坚持到他们的queryset没有高速缓存超时的危险(假设3个小时足够长以查看记录)。

  import datetime 

...

如果没有request.session.get('random_exp'):
request.session ['random_exp'] = %d_%d%(
datetime.datetime.strftime(datetime.datetime.now(),'%​​Y%m%dH'),
random.randrand(0,RANDOM_EXPERIENCES)

object_list = cache.get(random_exp_%s%request.session ['random_exp'])
如果不是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查询存储在缓存中。


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)
  ....

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?

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.

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)
    ....

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.

Update

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)

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天全站免登陆