Several times in the past I needed to fetch a list of random objects. And Today I decided to make a Mixin class to add a get_random() method to my managers:
# -*- coding: utf-8 -*- from random import sample class RandomObjectManager(object): """ Manager Mixin to implement get_random() in your models. You can override get_objects to tune the queriset To use, define your class: class MyManager(models.Manager, RandomObjectManager): DEFAULT_NUMBER = 5 # I can change that def get_objects(self): return self.filter(active=True) # Only active models plz class MyModel(models.Model): active = models.BooleanField() objects = MyManager() Now you can do: MyModel.objects.get_random() """ DEFAULT_NUMBER = 3 def get_objects(self): return self.all() def get_random(self, number=DEFAULT_NUMBER): """ Returns a set of random objects """ ids = self.get_objects().values_list('id', flat=True) amount = min(len(ids), number) picked_ids = sample(ids, amount) return self.filter(id__in=picked_ids)
fish2000: Hey, nice implementation w/ the inner class sir. Just an FYI tho: in my own investigations with this sort of thing, I found that calling random.seed() in the manager's init() method was necessary, to ensure the most randomish results.
Thomas Woolford: Surely this is less of a performance killer than reading every ID from the entire table and then making another separate query to grab the objects that you actually need....
Fernando Gutierrez: Aren't you supposed to use get_objects() instead?
Jj: Yes! I just fixed that, thanks