Getting Random objects from a Queryset in Django

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.

3 Responses to “Getting Random objects from a Queryset in Django”


  1. 1 name May 14, 2010 at 4:15 am

    how about preparing a list of random ids and then do a sql query WHERE ids IN (…) to escape from consecutive lists

  2. 3 kwalo May 14, 2010 at 5:01 pm

    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.


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Connecting to %s





Follow

Get every new post delivered to your Inbox.