I have the following model:
class Entry(models.Model):
name = models.Charfield(max_length=255)
client = models.Charfield(max_length=255)
Thats not the most performant way, but works:
from itertools import zip_longest
from django.db.models import Case, When
grouped_pks = []
for client in Entry.objects.values_list('client', flat=True).distinct():
grouped_pks.append(
Entry.objects.filter(client=client).values_list('pk', flat=True)
)
alternated_pks = [
x for x in
filter(
None,
sum(zip_longest(*grouped_pks), ())
)
]
alternated_pks_order = Case(
*[
When(pk=pk, then=position)
for position, pk in enumerate(alternated_pks)
]
)
entries = Entry.objects.filter(pk__in=alternated_pks).order_by(alternated_pks_order)
for entry in entries:
print('id: {} - client: {}'.format(entry.id, entry.client))
Expected output:
id: 8901 - client: google
id: 8890 - client: facebook
id: 8884 - client: google
id: 8894 - client: facebook
id: 8748 - client: google
id: 8891 - client: facebook
id: 8906 - client: google
id: 8909 - client: facebook
id: 8888 - client: google
id: 8895 - client: facebook
id: 8919 - client: google
id: 8910 - client: facebook
id: 8878 - client: google
id: 8896 - client: facebook
id: 8916 - client: google
id: 8902 - client: facebook
id: 8917 - client: google
id: 8885 - client: facebook
id: 8918 - client: google
id: 8903 - client: facebook
id: 8920 - client: google
id: 8886 - client: facebook
id: 8904 - client: facebook
id: 8905 - client: facebook
id: 8887 - client: facebook
id: 8911 - client: facebook
id: 8897 - client: facebook
id: 8912 - client: facebook
id: 8898 - client: facebook
id: 8899 - client: facebook
id: 8914 - client: facebook
id: 8900 - client: facebook
id: 8915 - client: facebook
This is python3 code, but if you want to use it with python 2, change the zip_longest function to izip_longest.
This code is nice, because we still work with Queryset, so all other Sorting, Ordering, Managers, Pagination and other stuff will still work.