Skip to content

Instantly share code, notes, and snippets.

@kaedroho
Created December 20, 2016 13:22
Show Gist options
  • Save kaedroho/0a9e1e69697b93e5dac311845bfa5586 to your computer and use it in GitHub Desktop.
Save kaedroho/0a9e1e69697b93e5dac311845bfa5586 to your computer and use it in GitHub Desktop.
def randomly_order_queryset_deterministically(queryset, salt):
"""
Applies a pseudo-random ordering on the queryset. For each object, a number
is generated by performing a CRC32 function on the object's ID and a salt.
So if you use the same salt, you get the same ordering.
We need to implement it this way so the same random ordering is preserved for
the subsequent AJAX requests.
"""
return queryset.extra(
select={
'random_order': 'contactsindex_crc32(id ::text || %s)'
},
select_params=(salt, ),
order_by=('random_order', 'id')
)
# -*- coding: utf-8 -*-
# Generated by Django 1.9.10 on 2016-12-20 12:48
from __future__ import unicode_literals
from django.db import migrations
CREATE_CRC32 = """
CREATE OR REPLACE FUNCTION contactsindex_crc32(text_string text) RETURNS bigint AS $$
DECLARE
tmp bigint;
i int;
j int;
byte_length int;
binary_string bytea;
BEGIN
IF text_string = '' THEN
RETURN 0;
END IF;
i = 0;
tmp = 4294967295;
byte_length = bit_length(text_string) / 8;
binary_string = decode(replace(text_string, E'\\\\', E'\\\\\\\\'), 'escape');
LOOP
tmp = (tmp # get_byte(binary_string, i))::bigint;
i = i + 1;
j = 0;
LOOP
tmp = ((tmp >> 1) # (3988292384 * (tmp & 1)))::bigint;
j = j + 1;
IF j >= 8 THEN
EXIT;
END IF;
END LOOP;
IF i >= byte_length THEN
EXIT;
END IF;
END LOOP;
RETURN (tmp # 4294967295);
END
$$ IMMUTABLE LANGUAGE plpgsql;
"""
DROP_CRC32 = "DROP FUNCTION contactsindex_crc32(text);"
class Migration(migrations.Migration):
dependencies = [
('myapp', '0001_initial'),
]
operations = [
migrations.RunSQL(CREATE_CRC32, DROP_CRC32)
]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment