2012-06-03 5 views
1

가정하자 나는이 다음과 같은 위치에 표시됩니다 3 그중 10 개체를 반환하는 검색어 세트 :의사 난수 순서의 검색어

[ display 1 position ]  [ display 2 position ]  [ display 3 position ] 

모델이 표현은 다음과 같다 :

class FeaturedContent(models.Model): 
    image = models.URLField() 
    position = models.PositiveSmallIntegerField(blank=True, null=True) 

여기서 position은 1, 2, 3 또는 지정되지 않음 (Null) 일 수 있습니다.

지정된 위치의 오브젝트를 제외하고 임의로 QuerySet을 정렬 할 수 있기를 원합니다. 그러나, 나는 수행하여 주문할 수 없습니다

featured_content = FeaturedContent.objects.order_by('-position', '?') 

내가 position = 2을 가지고 하나 개의 항목이 있고, 다른 모든 항목은 다음 항목이 위치 1 대신에 위치 2.

에 나타나는, Null 인 경우에 때문에

어떻게 주문하나요?

아마도 그것은 같은 딕셔너리 대신 목록, 뭔가 같은 데이터 것이 가장 것, 이것에 대해 생각 : 사이의 병합 정렬을하고, 나는 과정을 게시 할

`{'1': item or null, '2': item or null, '3': item or null, '?': [list of other items]}` 
+0

당신이해야 데이터베이스 내의 무작위 순서를 피할 수 있습니다. ([django documentation] (https://docs.djangoproject.com/en/dev/ref/models/querysets/#order-by)에서 지적했듯이) 느린! –

+0

그럼 위에서해야 할 일을하는 더 좋은 방법은 무엇입니까? – David542

답변

0

을 주문하고 정렬되지 않은 기록.

EDIT : 이것

발전기의 시작에서이 코드 (: StopIteration 힌트)에서 가능한 오류 조건이 많이 존재한다는

def posgen(posseq, arbseq, posattr='position', startpos=1): 
    posel = next(posseq) 
    for cur in itertools.count(startpos): 
    if getattr(posel, posattr) == cur: 
     yield posel 
     posel = next(posseq) 
    else: 
     yield next(arbseq) 

참고.

+0

감사합니다. 어떻게 완료했는지 보여 주시겠습니까? – David542

0

쿼리 세트를 반복하고 싶다면 두 개의 쿼리 세트를 주문하고 연결할 수 있습니다.

import itertools 

qs1 = FeaturedContent.objects.filter(position__isnull=False).order_by('-position') 
qs2 = FeaturedContent.objects.filter(position__isnull=True).order_by('?') 
featured_content = itertools.chain(qs1, qs2) 
for item in featured_content: 
    #do something with qs item 
    print item 

Upadate :

확실 위치 순서를 결정하고 "빈"공간이 null 위치와 요소에 의해 무작위로 교체하도록 요구하고 있기 때문이다. 효율적으로 무작위 순서를 수행하는 DB 백엔드를 사용하는 경우 취득하고자하는 기능 목록이 경우

featured = [] 
rands = [] 
for i in xrange(1, 20): 
    try: 
     x = FeaturedContent.objects.get(position=i) # assuming position is unique 
    except FeaturedContentDoesNotExist: 
     if not rands: 
      rands = list(FeaturedContent.objects.filter(position__isnull=True).order_by('?')[:20] 
     x = rands[0] 
     rands = rands[1:] 
    featured.append(x) 
+0

+1은 더 빠름 =). 그러나 -1은 널 위치가있는 다른 항목이 – okm

+0

일 때 항목 w/위치 2가 위치 2에 있어야한다는 요구 사항을 충족시키지 못합니다. 올바른 순서는 다음과 같습니다. 지정된. – David542

0

20, 너무 크지 않은 경우는 다음과 같이 그것을 할 수 :

# This will hold the result 
featured_dict = {} 

featured_pos = FeaturedContent.objects.filter(position__isnull=False).order_by('-position') 
featured_rand = FeaturedContent.objects.filter(position__isnull=True).order_by('?') 

pos_index = 0  
rand_index = 0 

for pos in range(1, 4): 
    content = None 

    if pos_index < len(featured_pos) and featured_pos[pos_index].position == pos: 
     content = featured_pos[pos_index] 
     pos_index += 1 

    elif rand_index < len(featured_rand): 
     content = featured_rand[rand_index] 
     rand_index += 1 

    featured_dict[str(pos)] = content 

# I'm not sure if you have to check for a valid index first before slicing 
featured_dict['?'] = featured_rand[rand_index:]