我想从模型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]中的内容?
答案 0 :(得分:8)
刚看过这个。这一行:
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。
答案 1 :(得分:3)
第二部分代码是正确的,但速度可能会慢一些,因为在SQL中生成一个ORDER BY RANDOM()
子句,它会对整个结果集进行混洗,然后根据它生成LIMIT
。 / p>
代码的第一位仍然需要评估整个结果集。例如,如果你的random_idx接近最后一个可能的索引怎么办?
更好的方法是从数据库中选择一个随机ID,然后选择它(这是一个主键查找,因此速度很快)。在您删除了某些内容的情况下,我们无法假设我们id
和1
之间的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}}
答案 2 :(得分:2)
对以上所有方面进行改进:
from random import choice
pks = A.objects.values_list('pk', flat=True)
random_pk = choice(pks)
random_obj = A.objects.get(pk=random_pk)
答案 3 :(得分: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中存在较大的间隙,也可以工作,例如,如果要在随机选择其中一个对象之前过滤查询集。
答案 4 :(得分: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倍。
答案 5 :(得分:0)
您可以使用“随机”模块中的“选择”
from .models import MyModel
from random import choice
MyRandomChoice = choice(MyModel.objects.all())
答案 6 :(得分:0)
如何计算最大主键并获得随机pk?
《Django ORM Cookbook》一书比较了以下函数的执行时间,以从给定模型中获取随机对象。
from django.db.models import Max
from myapp.models import Category
def get_random():
return Category.objects.order_by("?").first()
def get_random3():
max_id = Category.objects.all().aggregate(max_id=Max("id"))['max_id']
while True:
pk = random.randint(1, max_id)
category = Category.objects.filter(pk=pk).first()
if category:
return category
对一百万个数据库条目进行了测试:
In [14]: timeit.timeit(get_random3, number=100)
Out[14]: 0.20055226399563253
In [15]: timeit.timeit(get_random, number=100)
Out[15]: 56.92513192095794
见source。
看到这些结果后,我开始使用以下代码段:
from django.db.models import Max
import random
def get_random_obj_from_queryset(queryset):
max_pk = queryset.aggregate(max_pk=Max("pk"))['max_pk']
while True:
obj = queryset.filter(pk=random.randint(1, max_pk)).first()
if obj:
return obj
到目前为止,只要有一个 id,它就可以完成这项工作。 请注意,如果您将模型 id 替换为 uuid 或其他内容,则 get_random3 (get_random_obj_from_queryset) 函数将不起作用。此外,如果删除了太多实例,while 循环会减慢进程速度。