我试图从模型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个对象,但ID为10的对象不再存在了?我是否误解了A.objects.all()[random_idx]中的某些内容?
7条答案
按热度按时间2ledvvac1#
我刚看了这个。这句话:
据报道,这导致许多服务器瘫痪。
很遗憾,Erwans代码在访问非连续ID时导致错误。
还有另一种简单的方法可以做到这一点:
这样做的好处是它可以毫无错误地处理非顺序id。
aelbi1ox2#
改善以上所有方面:
zaq34kh63#
第二部分代码是正确的,但可能会慢一些,因为在SQL中,会生成一个
ORDER BY RANDOM()
子句,该子句对整个结果集进行洗牌,然后基于此获取一个LIMIT
。代码的第一位仍然需要计算整个结果集。例如,如果random_idx接近最后一个可能的索引,该怎么办?
一个更好的方法是从数据库中随机选择一个ID,并选择它(这是一个主键查找,所以速度很快)。我们不能假设在删除了某个内容的情况下,
1
和MAX(id)
之间的每个id
都是可用的。因此,下面是一个近似值,效果很好:ssgvzors4#
如何计算最大主键并得到随机pk?
书“Django ORM Cookbook”比较了以下函数的执行时间,以从给定模型中获得随机对象。
对一百万个DB条目进行了测试:
请参阅source。
看到这些结果后,我开始使用以下代码片段:
到目前为止,只要有一个id,它就能完成这项工作。注意,如果用uuid或其他东西替换模型id,get_random3(get_random_obj_from_queryset)函数将不起作用。此外,如果删除了太多示例,while循环将减慢进程。
8ljdwjyq5#
又道:
即使pk中存在较大的间隔也有效,例如,如果您希望在随机选取剩余对象之一之前过滤查询集。
编辑:修复了randint的调用(感谢@Quique)。停止参数是包含的。
https://docs.python.org/3/library/random.html#random.randint
z0qdvdin6#
我正在分享我最近的测试结果与Django 2.1.7,PostgreSQL 10.
看起来,使用random.choice()进行随机取数的速度要快2倍。
bfnvny8b7#
在python中,要获取
iterable object
的随机成员,如list,set, touple
或其他任何内容,可以使用random
模块。random
模块有一个名为choice
方法,该方法获取一个iterable
对象,并随机返回所有成员中的一个。所以因为
random.choice
想要一个可迭代对象,你可以在django中为queryset
使用这个方法。首先导入随机模块:
然后创建一个列表:
或者创建如下所示的query_set:
而要获取可迭代对象的随机成员,请使用choice方法:
3
完整代码:
2