Переадресация на другой вид проглатывает один аргумент

У меня есть ListView, который проверяет наличие прав пользователя и пересылает набор запросов или перенаправляет на другое представление в зависимости от прав пользователя:

class SelectRegisterListView(StoreMixin, ListView):
    template_name = f"{TEMPLATE_ROOT_SHELF}/select_register.html"

    def get_queryset(self):
        registers = Register.objects.filter(store = self.store)
        print(registers, registers.first().pk) ## works ... and 4
        if check_custom_registers_allowed(self.request) == True:
            return registers
        return redirect("select-quality", ins_id = self.kwargs["ins_id"], pg = self.kwargs["pg"], reg = registers.first().pk)

В моем urls.py есть следующее:

path("selectquality/<int:ins_id>/<int:pg>/<int:reg>", views.SelectRegisterListView.as_view(), name = 'select-quality'),

которая завершается с ошибкой NoReverseMatch:

Поиск для 'select-quality' с ключевыми аргументами '{'ins_id': 1849332, 'pg': 3, 'reg': ''}' не найден.

Теперь я попробовал разные значения вместо registers.first().pk и мне нужна помощь в понимании этого:

при добавлении int -> reg остается пустым - также происходит при добавлении str(4)

return redirect("select-quality", ins_id = self.kwargs["ins_id"], pg = self.kwargs["pg"], reg = 4)

Поиск для 'select-quality' с ключевыми аргументами '{'ins_id': 1849332, 'pg': 3, 'reg': ''}' не найден.

когда добавление str -> reg имеет значение, но не удается

return redirect("select-quality", ins_id = self.kwargs["ins_id"], pg = self.kwargs["pg"], reg = "test")

Поиск для 'select-quality' с ключевыми аргументами '{'ins_id': 1849332, 'pg': 3, 'reg': 'test'}' не найден.

Последний случай очевиден, reg должен быть типа int, а не str. Но почему первый подход не работает с reg = registers.first().pk?

Посмотрите, можете ли вы выполнить следующее и что вы получите:

from django.urls import reverse

reverse('select-quality', args=(1,2,3))
reverse('select-quality', kwargs={'ins_id': 1, 'pg': 2, 'reg': 3})

Если оба вызова разрешаются успешно, посмотрите, какие типы значений вы передаете вызову перенаправления.

В ListView метод get_query_set() используется для определения более сложных запросов, которые должны быть выполнены для сужения элементов модели, перечисленных в представлении. Вот пример из документации django https://docs.djangoproject.com/en/4.0/ref/class-based-views/generic-display/#listview:

class PublisherBookListView(ListView):

    template_name = 'books/books_by_publisher.html'

    def get_queryset(self):
        self.publisher = get_object_or_404(Publisher, name=self.kwargs['publisher'])
        return Book.objects.filter(publisher=self.publisher)

Поэтому get_queryset должен всегда возвращать кверисет.

Во время GET-запроса этот возвращаемый кверисет используется для рендеринга содержимого ListView с помощью метода get() и html-шаблона, определенного как "имя_шаблона". На этапе рендеринга кверисет добавляется в контекст рендеринга.

Если, как в вашем случае, вы возвращаете "redirect" HTTPResponse и передаете его как "queryset", результатом может быть что угодно, в зависимости от вашего html-шаблона.

Если вы хотите реагировать на набор запросов, то перепишите метод get(), вызовите get_queryset(), сделайте свои проверки и перенаправьте оттуда. Внутри get_queryset() просто выполните основной запрос.

class SelectQualityListView(StoreMixin, ListView):
    template_name = f"{TEMPLATE_ROOT_SHELF}/select_register.html"

    def get_queryset(self):
        return Register.objects.filter(store = self.store)

    def get(self, request, *args, **kwargs):
        if check_custom_registers_allowed(self.request) is not True:
           return redirect("select-quality", ins_id = self.kwargs["ins_id"], pg = self.kwargs["pg"], reg = registers.first().pk)
        super().get(request, *args, **kwargs)

примечание: это только для того, чтобы показать идею... в коде могут быть ошибки

Вернуться на верх