How to select random record with Django ORM
This post details how I solved displaying random banner on this very site. The solution does not have any prerequisites.Published: Sept. 8, 2020 Sponsored App Store
Recently I wanted to implement more sophisticated banners on this site to promote my iOS apps. Initially I had just one hardcoded banner in the template but that was not going to work for multiple banners.
The part that took the longest was to display random banner on a page. This involves mainly getting random record (or entity if you will) from your database. I have found quite a few solutions but they were either too complicated or relied on some preconditions like you had to have a table with no deleted records + sequential ids and then you could use something like last id or count and select random number from that.
My solution does not have any requirements but could be problematic if you needed to select from possibly 100s of thousands or more records.
Anyway, let's move to code. My
Banners can be toggled off with property
is_active so I am using Django ORM
filter together with
values to pull out all the available ids. Like this:
banner_ids = Banner.objects.filter(is_active=True).values('id')
Once that is done, we can check if the result is not empty and if not, utilize
random module to pick random element.
import random if len(banner_ids) > 0: random_id = random.choice(banner_ids)["id"] try: banner = Banner.objects.get(pk=random_id) except Banner.DoesNotExist: banner = None
banners_ids is basically "array" of key-value pairs, there is
["id"] subscript to pull out just the number. Once we have random id, we can use that to try to get record with the
And that is all!
I think this is pretty good for my usecase and for many other assuming you don't have tons of data to work with.
I have a few banners and the pages are cached so I don't almost have to even think about performance.
Note on memory usage
I have been recently informed by a reader that the above method might be memory intensive in certain situations. Theirs was Raspberry Pi and presumably large number of records.
A solution for this situation can be to use
order_by("?") which does random ordering at the database level and uses less memory.