Переадресация на другой вид проглатывает один аргумент
У меня есть 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)
примечание: это только для того, чтобы показать идею... в коде могут быть ошибки