Created
January 20, 2016 14:39
-
-
Save kezabelle/ec362e6ced35bf55fca4 to your computer and use it in GitHub Desktop.
a weird mishmash of doing an SQL "IN (x, y, z)" and covering consecutive ranges. For Django. Using Q objects and horrifying machinations.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def generate_integer_pk_range(flat_iterable): | |
""" | |
A bit of this is taken from : | |
http://code.activestate.com/recipes/496682-make-ranges-of-contiguous-numbers-from-a-list-of-i/#c2 | |
and a bit from: | |
https://github.com/kezabelle/django-inheritrix/blob/a4825612dbcc20add509c4bb49e93bdb1f8f409f/inheritrix.py#L44 | |
>>> x = MyModel.objects.values_list('pk', flat=True) | |
[1, 2...5, 9, 100...121] | |
>>> y = generate_integer_pk_range(x) | |
Q(pk=1) | Q(pk__range=(2, 5)) | Q(pk=9) | Q(pk__range=(100, 121) | |
>>> z = MyModel.objects.filter(y) | |
Would need expanding to cover supplying a related lookup. | |
""" | |
def yielder(): | |
flat_iterable_sorted = sorted(set(flat_iterable)) | |
leftovers = set() | |
for k, g in groupby(enumerate(flat_iterable_sorted), lambda (i,x):i-x): | |
result = map(operator.itemgetter(1), g) | |
num_in_result = len(result) | |
if num_in_result > 1: | |
first = result[0] | |
last = result[-1] | |
yield Q(pk__range=(first, last)) | |
else: | |
leftovers.add(result[0]) | |
if leftovers: | |
yield Q(pk__in=leftovers) | |
out = reduce(operator.or_, yielder()) | |
return out |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment