Django得到一个随机对象

时间:2014-04-02 15:49:23

标签: python django object random

我想从模型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]中的内容?

7 个答案:

答案 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,然后选择它(这是一个主键查找,因此速度很快)。在您删除了某些内容的情况下,我们无法假设我们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}}

答案 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 循环会减慢进程速度。