假设我有一个返回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)
其中position可以是1,2,3或未指定(Null)。
我希望能够为具有指定位置的对象随机排序除QuerySet。但是,我不能这样做:
featured_content = FeaturedContent.objects.order_by('-position', '?')
因为如果我有一个项目position = 2
,而所有其他项目都是Null
,那么该项目将显示在位置1而不是位置2.
我该怎么做这个订单?
考虑到这一点,也许最好将数据作为字典而不是列表,例如:
`{'1': item or null, '2': item or null, '3': item or null, '?': [list of other items]}`
答案 0 :(得分: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
)。
答案 1 :(得分: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:
由于您要求确保位置确定顺序,并且“空白”空格由具有空位置的元素随机替换。如果您想要获得的特色列表不是太大,在这种情况下为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)
答案 2 :(得分: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:]