Order queryset by alternating value

后端 未结 3 764
余生分开走
余生分开走 2020-12-09 05:27

I have the following model:

class Entry(models.Model):
    name = models.Charfield(max_length=255)
    client = models.Charfield(max_length=255)
3条回答
  •  一向
    一向 (楼主)
    2020-12-09 06:06

    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.

提交回复
热议问题