Randomization in DB feels nasty and better in python. But at the same time, it's not a good idea to bring all the data from DB to python memory just to ignore most of the results (especially in the production environment). we might need some sort of filtering also.
- So Basically we have data at DB,
- we wanna use the rand function of python
- and afterwords bring up the whole required data from DB.
Basically using 2 queries will be much less expensive than picking random in DB CPU (computing in DB) or loading whole data (heavy Network Utilization). Solutions explained must need a scalable nature trying to plan here won't work for a production environment espicially with filters, soft/hard deletes, or even with an is_public flag. because probably random id we generated might be deleted from the database or will be cut down in filters. Its a bad practice to assume max_id(records) == count(records).
(Ofcouce, If you do'not delete a percentage of data which is comparable to query uses, or if you dont wanna use any kond of filters, and if you are confident, random id which you can proceed with a random )
if you want only one items.
Refer ( @Valter Silva )
import random
mgr = models.Painting.objects
qs = mgr.filter(...)
random_id = random.choice(1, qs.count())-1 # <--- [ First Query Hit ]
random_paint = qs[random_id] ## <-- [ Second Query Hit ]
if you want 'n' items.
import random
req_no_of_random_items = 8 ## i need 8 random items.
qs = models.Painting.objects.filter(...)
## if u prefer to use random values often, you can keep this in cache.
possible_ids = list(qs.values_list('id', flat=True)) # <--- [ First Query Hit ]
possible_ids = random.choices(possible_ids, k=8)
random_paint = qs.filter(pk__in=possible_ids) ## in a generic case to get 'n' items.
or if you want to have a more optimized code for production, use a cachefunction to get ids of products:
from django.core.cache import cache
def id_set_cache(qs):
key = "some_random_key_for_cache"
id_set = cache.get(key)
if id_set is None:
id_set = list(qs.values_list('id', flat=True)
cache.set(key, id_set)
retrun id_set
order_by('?')
– user-124812948