2013-05-16 2 views
4

다른 해시 태그 쌍을 비교할 수있는 앱을 작성하고 있습니다.Django 쿼리 세트를 한 번 무작위로 만든 다음 반복합니다.

모델 :

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('?') O 이외의 일을 무작위의 더 나은 방법은 무엇

  1. ? 저는 MySQL을 사용하고 있는데, 여기에 대해서는 어떻게 보입니까 order_by('?') + MySQL = SLOOOOOOOW. 두 가지 제안이 있었고 쉽게 구현할 수있었습니다 (나는 random.shuffle(Competitors.objects.all())의 라인을 따라 생각하고있었습니다). 그러나 두 번째 질문으로 안내하는 곳을 어디에 놓을 지 확신하지 못했습니다.
  2. 랜덤 화가 한 번만 발생하는지 어떻게 확인합니까? 나는 사람들에게 같은 쌍을 반복해서 검토하게함으로써 사람들을 지루하게하고 싶지 않고, 어떤 쌍이 무작위로 한 번 이상 나타남으로써 결과를 포기하고 싶지 않습니다. 다른 사람들과 똑같은 목록을 모든 사람들이 볼 수 있기를 바랍니다.

나는 대답이 Manager 클래스에 있다고 생각하지만 실제로 이것은 장고가 호출 할 때 내 지식이 부족하다는 것을 의미합니다.

는 (나는 또한 결과 내 DB에 저장하기 것 같지 않는 문제가있어,하지만 다른, 아마 더 쉽게 해결, 문제입니다.)

답변

2

가 일관성을 유지하기 위해 임의 순서로 세션에 저장된 시드를 사용하여 시드 된 무작위로 정렬해야합니다. 불행하게도 당신은 순수 장고 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 열을 데이터베이스에 만들고 세션 중 하나에 정렬하는 것입니다.

0

크게 위의 그렉의 멋진 제안에 따라 내 솔루션 :

보기 :

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의 모습을 like : url(r'^hash/(\d*)$', compare_hashes)

감사합니다. 다시!

2

거기에 시드가있는 임의의 함수가 없으므로 PostgreSQL에서 Greg의 대답을 시도했지만 오류가 발생했습니다.어떤 사고 후, 나는 다른 방법을 가서 같은 작업을 더 좋아하는 파이썬 그 일, 준 내 1.5K 항목의 검색어에

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 

가 충분히 빠르게 작동합니다.

P. 그리고 쿼리 세트를 목록으로 변환 할 때 페이지 매기기 바로 전에이 함수를 실행하는 것이 좋습니다.

관련 문제