Jj's web stream

Django random object manager

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)

I've added this as a Django snippet and as a Gist.

Comments

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....

Thomas Woolford: ]

Jj: https://code.djangoproject.com/ticket/5267

Fernando Gutierrez: Aren't you supposed to use get_objects() instead?

Jj: Yes! I just fixed that, thanks