我正在编写一个应用程序,允许人们比较不同的主题标签对。
型号:
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})
我想要做的是,每位访问者随机化竞争对手的排序,然后遍历该随机列表。
问题:
bjects.order_by('?')
之外,有什么更好的随机化方法?我正在使用MySQL,我在这里看到了一些关于如何order_by('?')
+ MySQL = SLOOOOOOOW的事情。给出了一些建议,我可以很容易地实现一些东西(我正在思考random.shuffle(Competitors.objects.all())
)的内容,但我不知道我把它放在哪里,这引出了我的第二个问题... 我怀疑答案在于经理类,但实际上,这一切都归结为我对Django所谓的调用缺乏了解。
(我也遇到了一个问题,结果似乎没有保存到我的数据库,但这是一个不同的,可能更容易解决的问题。)
答案 0 :(得分:2)
要保持一致的随机顺序,您应该通过种子随机排序,并将种子存储在会话中。不幸的是你不能用纯粹的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
...
我怀疑在大多数情况下表演会成为一个问题;如果您最好的选择是在数据库中创建一些索引的sort_key列,这些列会定期使用随机值进行更新,并为会话中的其中一个订购。
答案 1 :(得分:2)
尝试了Greg对PostgreSQL的回答并得到了一个错误,因为那里没有种子的随机函数。经过一番思考之后,我又采取了另一种方式将这项工作交给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项目查询集上运行得足够快。
P.S。因为它将查询集转换为列表,所以最好在分页之前运行此函数。
答案 2 :(得分:0)
我的解决方案,主要基于Greg上面的精彩建议:
查看:
def compare_hashes(request, i=0):
i = int(i)
competitors = Competitors.objects.all()
DATABASE_ENGINE = settings.DATABASES['default']['ENGINE'].split('.')[-1]
if DATABASE_ENGINE == 'mysql':
if not request.session.get('random_seed',False):
ints = xrange(10000)
request.session['random_seed'] = sample(ints,1)[0]
seed = request.session['random_seed']
competitors = competitors.extra(select={'sort_key': 'RAND({})'.format(seed)})
randomized_competitors = competitors.order_by('sort_key')
try:
chosen_competitor = randomized_competitors[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': chosen_competitor.tag1, 'tag2': chosen_competitor.tag2, 'action':'/hash/{}'.format(i), 'done': False})
模板(使用Django-bootstrap-toolkit但仍需要一些工作):
{% extends 'base.html' %}
{% load bootstrap_toolkit %}
{% block title %}Title{% endblock %}
{% block big_title %}Title{% endblock %}
{% block main-content %}
<h3>Hash-to-Hash</h3>
{% if done %}
<div class="row-fluid">
<div class="span8">
<h4>You're Done!</h4>
<p>Thanks so much!</p>
</div>
</div>
{% else %}
<div class="row-fluid">
<div class="span6" id="tag1">
<h4>{{ tag1.text }}</h4>
</div>
<div class="span6" id="tag2">
<h4>{{ tag2.text }}</h4>
</div>
<div class="span8">
<form action="{{ action }}" method="post">
{% csrf_token %}
<!-- {{ form|as_bootstrap }} -->
{% bootstrap_form form layout="vertical" %}
<div class="form-actions">
<button type="submit" class="btn btn-success" name="yes">
YES, I think these two tags are co-referential
</button>
<button type="submit" class="btn btn-danger" name="no">
NO, I don't think these two tags are co-referential
</button>
</div>
</form>
</div>
</div>
{% endif %}
{% endblock %}
URLconf如下所示:url(r'^hash/(\d*)$', compare_hashes)
再次感谢!