1

10個のオブジェクトを返すQuerySetがあり、そのうち3個が次の位置に表示されるとします。

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

それを表すモデルは次のとおりです。

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

ここで、位置は1、2、3、または指定なし(Null)のいずれかになります。

指定された位置のオブジェクトを除いて、QuerySetをランダムに並べ替えることができるようにしたい。ただし、次のようにして注文することはできません。

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

を持っているアイテムが1つposition = 2あり、他のすべてのアイテムがNullである場合、そのアイテムは位置2ではなく位置1に表示されるためです。

この注文はどのように行いますか?

これについて考えると、データをリストではなくdictとして使用するのがおそらく最善でしょう。たとえば、次のようになります。

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

3 に答える 3

0

順序付けされたレコードと順序付けされていないレコードの間でマージソートを実行して、後処理します。

編集:

このためのジェネレータの始まり:

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)

このコードには多くのエラー状態が発生する可能性があることに注意してください(ヒント:) StopIteration

于 2012-06-03T06:23:42.200 に答える
0

クエリセットを反復処理するだけの場合は、2つのクエリセットを作成し、それらを並べ替えてチェーンすることができます。

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 

更新:

位置が順序を決定し、「空白」のスペースがnull位置の要素にランダムに置き換えられることを確認するように求めているためです。取得したい注目リストが大きすぎない場合は、この場合は20

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)
于 2012-06-03T07:31:18.617 に答える
0

ランダムな順序付けを効率的に行う db バックエンドを使用する場合は、次のようにすることができます。

# 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:]
于 2012-06-03T22:14:17.790 に答える