Произвольный порядок запросов для каждого пользователя с пагинацией в Django

Я хочу произвольно упорядочить набор запросов, который фиксирован для каждого пользователя. Когда я использую order_by("?"), порядок меняется каждый раз, но я хочу, чтобы для каждого пользователя был свой порядок, который не будет меняться в следующий раз. Например, для первого пользователя заказ <QuerySet [obj1, obj5, obj3, obj4, obj2]>, а для второго <QuerySet [obj5, obj2, obj1, obj3, obj4]> и заказ для первого пользователя не меняется, но отличается от заказов других пользователей. Как я могу это сделать?

В Django нет встроенной функции для такой перестановки. Но вы можете реализовать это самостоятельно.

Чтобы реализовать это, вам нужно сохранить случайное значение seed, соответствующее пользователю. Я полагаю, что у вас есть идентификатор пользователя, связанный с пользователем, вы можете использовать его в качестве начального значения.

Теперь вам нужно использовать это начальное значение во встроенной в Python программе random для генерации случайной перестановки.

Пример:

import random

numbers = [10, 20, 30, 40, 50, 60]
print("Original list: ", numbers)
random.seed(4)
random.shuffle(numbers)
print("Shuffled list ", numbers)
# Output [40, 60, 50, 10, 30, 20]

random.seed(4)
random.shuffle(numbers)
print("Reshuffled list ", numbers)
# Output [40, 60, 50, 10, 30, 20]

random.seed(5)
random.shuffle(numbers)
print("Reshuffled list ", numbers)
# Output [60, 40, 10, 20, 30, 50]

Преобразуйте тот же QuerySet в список и передайте его в random.shuffle(qs_list), получите id пользователя и передайте его в random.seed(user_id).

Пример:

import random
random.seed(user_id)
random.shuffle(qs_list)
# qs_list is shuffled according to user's id

Вы можете сделать это несколькими способами, и это зависит от того, будет ли меняться основной набор запросов (добавление/удаление экземпляров). Самый простой способ - хранить рандомизированный кверисет как переменную в модели User. Это может быть, например, CharField, которая будет хранить идентификаторы, разделенные запятыми.

models.py

User(...):
    ...
    my_queryset = models.CharField("My QuerySet", max_lenght=512, default="")

    def set_queryset(self, queryset):
        self.my_queryset = ",".join([x.id for x in queryset])
        self.save()

    def get_queryset(self):
        list_of_ids = [int(x) for x in self.my_queryset.split(",")]
        queryset = [queryset.append(MyModel.objects.get(id=i)) for i in list_of_ids]
        return queryset
    

использование:

user = User.objects.get(id=1)
randomized_qs = [obj1, obj5, obj3, obj4, obj2]

user.get_queryset()   # gives []
if not user.my_queryset:
    user.set_queryset(randomized_qs)
user.get_queryset()   # gives [obj1, obj5, obj3, obj4, obj2]
Вернуться на верх