python 如何使用 Django 获取两条随机记录
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1731346/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to get two random records with Django
提问by Matt McCormick
How do I get two distinct random records using Django? I've seen questions about how to get one but I need to get two random records and they must differ.
如何使用 Django 获得两个不同的随机记录?我已经看到有关如何获得一个的问题,但我需要获得两个随机记录,它们必须不同。
采纳答案by Bartek
If you specify the random operator in the ORM I'm pretty sure it will give you two distinct random results won't it?
如果您在 ORM 中指定随机运算符,我很确定它会给您两个不同的随机结果,不是吗?
MyModel.objects.order_by('?')[:2] # 2 random results.
回答by CryingCyclops
The order_by('?')[:2]
solution suggested by other answers is actually an extraordinarily bad thing to do for tables that have large numbers of rows. It results in an ORDER BY RAND()
SQL query. As an example, here's how mysql handles that (the situation is not much different for other databases). Imagine your table has one billion rows:
order_by('?')[:2]
对于具有大量行的表,其他答案建议的解决方案实际上是一件非常糟糕的事情。它产生一个ORDER BY RAND()
SQL 查询。例如,这里是 mysql 如何处理它(其他数据库的情况没有太大不同)。想象一下你的表有 10 亿行:
- To accomplish
ORDER BY RAND()
, it needs aRAND()
column to sort on. - To do that, it needs a new table (the existing table has no such column).
- To do that, mysql creates a new, temporary table with the new columns and copies the existing ONE BILLION ROWS OF DATA into it.
- As it does so, it does as you asked, and runs rand() for every row to fill in that value. Yes, you've instructed mysql to GENERATE ONE BILLION RANDOM NUMBERS. That takes a while. :)
- A few hours/days later, when it's done it now has to sort it. Yes, you've instructed mysql to SORT THIS ONE BILLION ROW, WORST-CASE-ORDERED TABLE (worst-case because the sort key is random).
- A few days/weeks later, when that's done, it faithfully grabs the two measly rows you actually needed and returns them for you. Nice job. ;)
- 为了完成
ORDER BY RAND()
,它需要一RAND()
列进行排序。 - 为此,它需要一个新表(现有表没有这样的列)。
- 为此,mysql 使用新列创建一个新的临时表,并将现有的 10 亿行数据复制到其中。
- 这样做时,它会按照您的要求执行,并为每一行运行 rand() 以填充该值。是的,您已经指示 mysql 生成十亿个随机数。这需要一段时间。:)
- 几个小时/几天后,当它完成时,它现在必须对其进行排序。是的,您已经指示 mysql 对这个十亿行、最坏情况排序的表进行排序(最坏情况,因为排序键是随机的)。
- 几天/几周后,完成后,它会忠实地抓取您实际需要的两行微不足道的行并将它们归还给您。不错的工作。;)
Note: just for a little extra gravy, be aware that mysql will initially try to create that temp table in RAM. When that's exhausted, it puts everything on hold to copy the whole thing to disk, so you get that extra knife-twist of an I/O bottleneck for nearly the entire process.
注意:只是为了一点额外的肉汁,请注意 mysql 最初会尝试在 RAM 中创建该临时表。当它耗尽时,它会暂停一切以将整个内容复制到磁盘,因此您几乎在整个过程中都会遇到 I/O 瓶颈的额外问题。
Doubters should look at the generated query to confirm that it's ORDER BY RAND()
then Google for "order by rand()" (with the quotes).
怀疑者应该查看生成的查询以确认它是ORDER BY RAND()
Google 的“order by rand()”(带引号)。
A much better solution is to trade that one reallyexpensive query for three cheap ones (limit/offset instead of ORDER BY RAND()
):
一个更好的解决方案是将一个非常昂贵的查询换成三个便宜的查询(限制/偏移量而不是ORDER BY RAND()
):
import random
last = MyModel.objects.count() - 1
index1 = random.randint(0, last)
# Here's one simple way to keep even distribution for
# index2 while still gauranteeing not to match index1.
index2 = random.randint(0, last - 1)
if index2 == index1: index2 = last
# This syntax will generate "OFFSET=indexN LIMIT=1" queries
# so each returns a single record with no extraneous data.
MyObj1 = MyModel.objects.all()[index1]
MyObj2 = MyModel.objects.all()[index2]
回答by dnit13
For the future readers.
对于未来的读者。
Get the the list of ids of all records:
获取所有记录的 id 列表:
my_ids = MyModel.objects.values_list('id', flat=True)
my_ids = list(my_ids)
Then pick n random ids from all of the above ids:
然后从上述所有 id 中选择 n 个随机 id:
n = 2
rand_ids = random.sample(my_ids, n)
And get records for these ids:
并获取这些 id 的记录:
random_records = MyModel.objects.filter(id__in=rand_ids)
回答by wsorenson
Object.objects.order_by('?')[:2]
Object.objects.order_by('?')[:2]
This would return two random-ordered records. You can add
这将返回两个随机排序的记录。你可以加
distinct()
if there are records with the same value in your dataset.
如果您的数据集中存在具有相同值的记录。
回答by David Wong
About sampling n random values from a sequence, the random lib could be used,
关于从序列中采样 n 个随机值,可以使用随机库,
random.Random().sample(range(0,last),2)
will fetch 2 random samples from among the sequence elements, 0 to last-1
将从序列元素中获取 2 个随机样本,从 0 到 last-1
回答by Pasha Maigutyak
from django.db import models
from random import randint
from django.db.models.aggregates import Count
class ProductManager(models.Manager):
def random(self, count=5):
index = randint(0, self.aggregate(count=Count('id'))['count'] - count)
return self.all()[index:index + count]
You can get different number of objects.
您可以获得不同数量的对象。