Django得到一个随机对象

问题描述 投票:4回答:4

我试图从模型A中获取一个随机对象

目前,它正在使用此代码:

random_idx = random.randint(0, A.objects.count() - 1)
random_object = A.objects.all()[random_idx]

但我觉得这段代码更好:

random_object = A.objects.order_by('?')[0]

哪一个是最好的?使用第一个代码删除对象可能出现问题?因为,例如,我可以有10个对象但是数字10作为id的对象不再存在?我在A.objects.all()[random_idx]中误解了什么吗?

python django object random
4个回答
10
投票

刚看过这个。这条线:

random_object = A.objects.order_by('?')[0]

据报道,它已经摧毁了许多服务器

不幸的是,Erwans代码在访问非顺序ID时导致错误。

还有另一种简短的方法:

import random

items = Product.objects.all()

# change 3 to how many random items you want
random_items = random.sample(items, 3)
# if you want only a single random item
random_item = random.choice(items)

这样做的好处是它可以无错误地处理非顺序ID。


3
投票

第二位代码是正确的,但可能会更慢,因为在SQL中生成一个ORDER BY RANDOM()子句,它会对整个结果集进行混洗,然后根据它来获取LIMIT

第一部分代码仍然需要评估整个结果集。例如,如果你的random_idx接近最后一个可能的索引怎么办?

更好的方法是从数据库中选择一个随机ID,并选择它(这是一个主键查找,所以它很快)。我们不能假设我们在id1之间的每个MAX(id)都可用,如果您删除了某些内容。所以下面是一个很好的近似值:

import random

# grab the max id in the database
max_id = A.objects.order_by('-id')[0].id

# grab a random possible id. we don't know if this id does exist in the database, though
random_id = random.randint(1, max_id + 1)

# return an object with that id, or the first object with an id greater than that one
# this is a fast lookup, because your primary key probably has a RANGE index.
random_object = A.objects.filter(id__gte=random_id)[0]

1
投票

另一种方式:

pks = A.objects.values_list('pk', flat=True)
random_idx = randint(0, len(pks))
random_obj = A.objects.get(pk=pks[random_idx])

即使pks中存在较大的间隙,也可以工作,例如,如果要在随机选择其中一个剩余对象之前过滤查询集。


0
投票

我正在与Django 2.1.7,PostgreSQL 10分享我最新的测试结果。

students = Student.objects.all()
for i in range(500):
    student = random.choice(students)
    print(student)

# 0.021996498107910156 seconds

for i in range(500):
    student = Student.objects.order_by('?')[0]
    print(student)

# 0.41299867630004883 seconds

使用random.choice()进行随机提取似乎要快2倍。

© www.soinside.com 2019 - 2024. All rights reserved.