Reputation: 5578
I know this question has been asked many times, but most of the answers use this method : MyModel.objects.order_by('?')[:4]
which will kill the database in the second day of production.
I'm looking for a faster and lightweight solution, I'm using the one below for now, but I would like to get more than 1 random query (4 for example).
views.py
last = MyModel.objects.count() - 1
random_int = random.randint(0, last)
records = MyModel.objects.all()[random_int] #one record only
Any solution ?
Upvotes: 0
Views: 72
Reputation: 53699
As long as you need a reasonable number of elements (such as 4), I'd sample based on the queryset index rather than the id. The drawback is that you need 4 queries instead of 1, but this way you get a consistent performance that doesn't depend on the number and size of gaps in between your primary key values.
count = MyModel.objects.count()
sample = random.sample(range(count), 4)
records = [MyModel.objects.all()[i] for i in sample]
Indexing a queryset uses LIMIT
and OFFSET
, so the indexing is based on the number of rows in the database, not on the id.
Upvotes: 2
Reputation: 15738
Use in keyword and generate random sample of numbers
random_num_sample = random.sample(range(0, last), 4)
records = MyModel.objects.filter(id__in=random_num_sample)
If the database gets frequent deletes than this solution is not viable, If deletes are not moderate you can still use following by randomizing sample with more than 4 elements
Upvotes: 2
Reputation: 9931
You can use in keyword.
random_num = [random.randint(0, last) for i in range(4)]
Then use
queryset_obj = MyModel.objects.filter(id__in=random_num)
Upvotes: 1