Marcolac
Marcolac

Reputation: 931

Randomize queryset deterministically

I have a queryset in Django :

Books.objects.filter(name=variable)

I would like to display this list randomly across my users (two different users will not see the books in the same order). But I want the order to remain the same for the same user if he comes back several times.

So is there a way, given an integer specific to my user (let say his user.id), to randomize the queryset ?

Thank you very much !

Upvotes: 2

Views: 261

Answers (2)

Burhan Khalid
Burhan Khalid

Reputation: 174642

You could randomize it on the database:

Books.objects.filter(name=variable).order_by('?')

But it would be best to store the list in a cache and then randomize the cached list.

For development purposes you can use a dummy cache, in your settings.py:

CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.dummy.DummyCache',
    }
}

In production you should use a supported cache.

Once that is setup, in your view at the first view that your user lands on, fetch the items from the database and store them in the cache:

import random

from django.core.cache import cache

@login_required
def index(request):
   cache_key = '{0}-books'.format(request.user.pk)
   book_list = cache.get(cache_key)
   if not book_list:
      # There was nothing in the cache, so we fetch the items
      # and add them in the cache

      # Here we set it to expire after 3600 seconds (1 hour)
      book_list = list(Book.objects.filter(name=variable))
      random.shuffle(book_list)
      cache.set(cache_key, book_list, 3600)


   # the rest of your code

Upvotes: 2

Jon Clements
Jon Clements

Reputation: 142176

You can create a separate random.Random object:

from random import Random

r = Random()
r.seed(some_user_id)
books = Books.objects.filter(name=variable)
jumbled = sorted(books, key=lambda L: r.random())

Upvotes: 1

Related Questions