When providing related or suggested info to the user in a website, it’s a common practice to obtain a random set of items. To do this in django the “usual” way is:
Book.objects.all().order_by('?')[:10]
The above code, sorts all books in a random order and then picks the first 10 objects. This approach is not really efficient en MySQL. Since the “ORDER BY ?” clause is really expensive. So, a good way to obtain random elemets (actually a random slice) is the following:
import random
count = Book.objects.all().count()
slice = random.random() * (count - 10)
Book.objects.all()[slice: slice+10]
The above code selects a random position for starting a slice (the next items are going to be consecutive). So it’s not really random.
Another approach is to get the random ids from Python:
from random import sample
count = Book.objecs.all().count()
rand_ids = sample(xrange(1, count), 10)
Book.objects.filter(id__in=rand_ids)
This last solution works fine for consecutive ids, where there are no missing elements. But you can always re call it until you have all the items you want.
how about preparing a list of random ids and then do a sql query WHERE ids IN (…) to escape from consecutive lists
yes that should work too!
The problem with your solution is that you can never be sure that ids in the database are consecutive, so you may loop forever, trying to fetch objects that do not exist.
I’d go with name’s solution.