Erw*_*wan 4 python random django object
我试图从模型A中获取一个随机对象
目前,它正在使用此代码:
random_idx = random.randint(0, A.objects.count() - 1)
random_object = A.objects.all()[random_idx]
Run Code Online (Sandbox Code Playgroud)
但我觉得这段代码更好:
random_object = A.objects.order_by('?')[0]
Run Code Online (Sandbox Code Playgroud)
哪一个是最好的?使用第一个代码删除对象可能出现问题?因为,例如,我可以有10个对象但是数字10作为id的对象不再存在?我在A.objects.all()[random_idx]中误解了什么吗?
luk*_*aus 11
刚看过这个.这条线:
random_object = A.objects.order_by('?')[0]
Run Code Online (Sandbox Code Playgroud)
据报道,它已经摧毁了许多服务器
不幸的是,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)
Run Code Online (Sandbox Code Playgroud)
这样做的好处是它可以无错误地处理非顺序ID.
计算最大主键并获得随机 pk 怎么样?
\n\xe2\x80\x98 Django ORM Cookbook \xe2\x80\x99书比较以下函数的执行时间,以从给定模型中获取随机对象。
\nfrom django.db.models import Max\nfrom myapp.models import Category\n\ndef get_random():\n return Category.objects.order_by("?").first()\n\ndef get_random3():\n max_id = Category.objects.all().aggregate(max_id=Max("id"))[\'max_id\']\n while True:\n pk = random.randint(1, max_id)\n category = Category.objects.filter(pk=pk).first()\n if category:\n return category\nRun Code Online (Sandbox Code Playgroud)\n对一百万个数据库条目进行了测试:
\nIn [14]: timeit.timeit(get_random3, number=100)\nOut[14]: 0.20055226399563253\n\nIn [15]: timeit.timeit(get_random, number=100)\nOut[15]: 56.92513192095794\nRun Code Online (Sandbox Code Playgroud)\n参见源码。
\n看到这些结果后,我开始使用以下代码片段:
\nfrom django.db.models import Max\nimport random\n\ndef get_random_obj_from_queryset(queryset):\n max_pk = queryset.aggregate(max_pk=Max("pk"))[\'max_pk\']\n while True:\n obj = queryset.filter(pk=random.randint(1, max_pk)).first()\n if obj:\n return obj\nRun Code Online (Sandbox Code Playgroud)\n到目前为止,只要有 id,它就可以完成这项工作。\n请注意,如果将模型 id 替换为 uuid 或其他内容,则 get_random3 (get_random_obj_from_queryset) 函数将\xe2\x80\x99t 工作。此外,如果删除了太多实例,则 while 循环会减慢进程速度。
\n代码的第二位是正确的,但可能会更慢,因为在 SQL 中,它会生成一个ORDER BY RANDOM()子句,该子句将整个结果集打乱,然后LIMIT根据它进行处理。
代码的第一位仍然必须评估整个结果集。例如,如果您的 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]
Run Code Online (Sandbox Code Playgroud)
改进以上所有内容:
from random import choice
pks = A.objects.values_list('pk', flat=True)
random_pk = choice(pks)
random_obj = A.objects.get(pk=random_pk)
Run Code Online (Sandbox Code Playgroud)