Python 将Django查询集随机化一次,然后遍历它

Python 将Django查询集随机化一次,然后遍历它,python,django,python-2.7,Python,Django,Python 2.7,我正在编写一个应用程序,允许人们比较不同的哈希标签对 型号: class Competitors(models.Model): tag1 = models.ForeignKey('Hashtag', related_name='+') tag2 = models.ForeignKey('Hashtag', related_name='+') votes = models.PositiveIntegerField(default=0, null=False) def co

我正在编写一个应用程序,允许人们比较不同的哈希标签对

型号:

class Competitors(models.Model):
    tag1 = models.ForeignKey('Hashtag', related_name='+')
    tag2 = models.ForeignKey('Hashtag', related_name='+')
    votes = models.PositiveIntegerField(default=0, null=False)
def compare_hashes(request, i=None):
    i = i or 0
    try:
        competitors = Competitors.objects.order_by('?')[i]
    except IndexError:
        return render(request, 'hash_to_hash.html',
            {'tag1': '', 'tag2': '', i: 0, 'done': True})

    if request.method == 'POST':
        form = CompetitorForm(request.POST)
        if form.is_valid():
            if "yes" in request.POST:
                competitors.votes += 1
                competitors.save()
        i += 1
        return render(request, 'hash_to_hash.html',
                  {'tag1': competitors.tag1, 'tag2': competitors.tag2, i: i, 'done': False})

    else:
        return render(request, 'hash_to_hash.html',
                  {'tag1': competitors.tag1, 'tag2': competitors.tag2, i: i, 'done': False})
查看:

class Competitors(models.Model):
    tag1 = models.ForeignKey('Hashtag', related_name='+')
    tag2 = models.ForeignKey('Hashtag', related_name='+')
    votes = models.PositiveIntegerField(default=0, null=False)
def compare_hashes(request, i=None):
    i = i or 0
    try:
        competitors = Competitors.objects.order_by('?')[i]
    except IndexError:
        return render(request, 'hash_to_hash.html',
            {'tag1': '', 'tag2': '', i: 0, 'done': True})

    if request.method == 'POST':
        form = CompetitorForm(request.POST)
        if form.is_valid():
            if "yes" in request.POST:
                competitors.votes += 1
                competitors.save()
        i += 1
        return render(request, 'hash_to_hash.html',
                  {'tag1': competitors.tag1, 'tag2': competitors.tag2, i: i, 'done': False})

    else:
        return render(request, 'hash_to_hash.html',
                  {'tag1': competitors.tag1, 'tag2': competitors.tag2, i: i, 'done': False})
我想做的是,每个访问者随机排列竞争对手对象的顺序,然后遍历随机列表

问题:

class Competitors(models.Model):
    tag1 = models.ForeignKey('Hashtag', related_name='+')
    tag2 = models.ForeignKey('Hashtag', related_name='+')
    votes = models.PositiveIntegerField(default=0, null=False)
def compare_hashes(request, i=None):
    i = i or 0
    try:
        competitors = Competitors.objects.order_by('?')[i]
    except IndexError:
        return render(request, 'hash_to_hash.html',
            {'tag1': '', 'tag2': '', i: 0, 'done': True})

    if request.method == 'POST':
        form = CompetitorForm(request.POST)
        if form.is_valid():
            if "yes" in request.POST:
                competitors.votes += 1
                competitors.save()
        i += 1
        return render(request, 'hash_to_hash.html',
                  {'tag1': competitors.tag1, 'tag2': competitors.tag2, i: i, 'done': False})

    else:
        return render(request, 'hash_to_hash.html',
                  {'tag1': competitors.tag1, 'tag2': competitors.tag2, i: i, 'done': False})
  • 除了o
    objects.order\u by(“?”)
    ,还有什么更好的随机化方法?我正在使用MySQL,我在这里看到了一些关于如何按(“?”)排序的内容。这里给出了一些建议,我可以很容易地实现一些东西(我是按照
    random.shuffle(Competitors.objects.all())
    的思路思考的),但我不确定我会把它放在哪里,这就引出了我的第二个问题
  • 如何确保随机化只发生一次?我不想让人们一次又一次地回顾同一对,让他们感到厌烦,我也不想让一些对随机出现不止一次,从而丢掉我的结果。我希望每个人都看到相同的列表,只是顺序不同
  • 我怀疑答案在于管理类,但事实上,这一切都归结为我对Django何时调用的知识不足


    (我也遇到了一个问题,结果似乎没有保存到我的数据库中,但这是一个不同的问题,可能更容易解决。)

    要保持一致的随机顺序,您应该按种子随机排序,种子存储在会话中。不幸的是,您无法使用纯django orm实现这一点,但使用mysql则非常简单:

    import random
    from django.conf import settings
    
    # there might be a better way to do this...
    DATABASE_ENGINE = settings.DATABASES[settings.DATABASES.keys()[0]]['ENGINE'].split('.')[-1]
    
    def compare_hashes(request, i=None):
        competitors = Competitors.objects.all()
    
        if DATABASE_ENGINE == 'mysql':
            if not request.session.get('random_seed', False):
                request.session['random_seed'] = random.randint(1, 10000)
            seed = request.session['random_seed']
            competitors = competitors.extra(select={'sort_key': 'RAND(%s)' % seed}).order_by('sort_key')
    
        # now competitors is randomised but consistent for the session
        ...
    

    我怀疑在大多数情况下,绩效会成为一个问题;如果您的最佳选择是在数据库中创建一些索引的排序键列,这些列会定期使用随机值进行更新,并在会话中对其中一列进行排序。

    我的解决方案主要基于Greg上面令人敬畏的建议:

    视图:

    模板(使用但仍需要一些工作):

    {%extends'base.html%}
    {%load bootstrap_toolkit%}
    {%block title%}标题{%endblock%}
    {%block big_title%}title{%endblock%}
    {%block main content%}
    散列到散列
    {%if done%}
    你完了!
    非常感谢

    {%else%} {{tag1.text} {{tag2.text} {%csrf_令牌%} {%bootstrap_form layout=“vertical”%} 是的,我认为这两个标签是相互参照的 不,我不认为这两个标签是相互参照的 {%endif%} {%endblock%}
    URLconf如下所示:
    url(r'^hash/(\d*)$,比较散列)


    再次感谢

    在PostgreSQL上尝试了Greg的答案,但出现了一个错误,因为没有带种子的随机函数。经过一番思考,我选择了另一种方式,将工作交给了Python,Python更喜欢这样的任务:

    def order_items_randomly(request, items):
        if not request.session.get('random_seed', False):
            request.session['random_seed'] = random.randint(1, 10000)
        seed = request.session['random_seed']
        random.seed(seed)
        items = list(items)
        random.shuffle(items)
        return items
    
    在我的1.5k物品查询集上工作足够快

    另外,在将queryset转换为list时,最好在分页之前运行此函数