Skip to content

Instantly share code, notes, and snippets.

@kezabelle
Created January 20, 2016 14:39
Show Gist options
  • Save kezabelle/ec362e6ced35bf55fca4 to your computer and use it in GitHub Desktop.
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.
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