beugene
@beugene
Oracle Developer, Delphi, Python, Django

Работа с классом RedirectView в Django 1.10, не вызывается метод get_redirect_url()?

Возник вопрос в корректности работы класса RedirectView в Django 1.10.
Есть подозрение, что я делаю что то неправильно, но что - не понимаю.

Коротко о сути задачи.
Сайт реализует логику работы различных конкурсов.
Участники могут зарегистрироваться в нескольких конкурсах и публиковать свои материалы.
Пользователь регистрируется и автоматически попадает на страницу одного из конкурсов.
Если нужно пользователю, в меню сайта можно перейти в раздел доступных конкурсов и выбрать другой конкурс.
После выбора, система запоминает этот выбор и возвращает пользователя на страницу работы с этим конкурсом.

Для реализации логики использовал ListView для списка доступных конкурсов и RedirectView для сохранения выбора и возврата на основную страницу.
Написал код. Первые два переключения конкурсов выполняются корректно. Последующие переключения не выполняются.
Из отладчика вижу, что не вызывается метод get_redirect_url() в котором запоминается id конкурса.
Не понимаю почему перестаёт работать.

Итак, есть такой views.py:

## views.py  

# только выдержка используемых классов в данной задаче
class AwardContextMixin(ContextMixin):
    
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        # Основной конкурс
        # Если пользователь ранее выбрал конкурс то выбираем этот конкурс
        if self.request.user.is_authenticated():
            user = self.request.user
            profile_user = get_object_or_404(ProfileUser, user=user)            
            if profile_user is not None:
                award_id = self.request.session.get('chosen_award', None)
                if award_id is None:
                    award = Award.get_active_award()
                    context['award'] = award
                    self.request.session['chosen_award'] = award.id
                else:
                    award = Award.objects.get(pk=award_id)
                    context['award'] = award
        else:
            context['award'] = Award.get_active_award()
        return context


class AwardMemberChooseAwardPageView(ListView, AwardContextMixin):
    template_name = 'choose_award_list.html'
    model = AwardProfileUser

    def get_queryset(self):
        print('AwardMemberChooseAwardPageView.get_queryset')
        qs = None
        if self.request.user.is_authenticated():
            user = self.request.user
            profile_user = get_object_or_404(ProfileUser, user=user)
            if profile_user is not None:
                qs = AwardProfileUser.objects.filter(
                    profile_user=profile_user,
                    is_agree_with_terms=True,
                    award__is_active=True
                )
        return qs


class AwardMemberStoreAwardPageView(RedirectView):
    permanent = True
    query_string = False
    pattern_name = 'awards:private_room'
    # url = '/account/private_room/'
    
    def get_redirect_url(self, *args, **kwargs):
        print('AwardMemberStoreAwardPageView.get_redirect_url')
        # без этого возникает ошибка 410
        self.url = reverse(self.pattern_name)
        # берем значение параметра из url
        award_id = kwargs.get('award_id', None)
        if award_id is not None:
            # запоминаем в сессии
            self.request.session['chosen_award'] = award_id
        return super().get_redirect_url(*args, **kwargs)


class AwardPrivateRoomPageView(TemplateView, AwardContextMixin):
    template_name = 'private_room.html'

    def get_context_data(self, **kwargs):
        print('AwardPrivateRoomPageView.get_context_data')
        context = super().get_context_data(**kwargs)
        # Далее готовим данные для шаблона
        # ...
        return context


## urls.py
urlpatterns = [
    url(r'account/private_room/$', AwardPrivateRoomPageView.as_view(), name='private_room'),
    url(r'account/choose_award/$', AwardMemberChooseAwardPageView.as_view(), name='choose_award'),
    url(r'account/choose_award/(?P<award_id>[0-9]+)/$', AwardMemberStoreAwardPageView.as_view(), name='store_award'),
]


Запускаю в режиме отладки. Регистрируюсь.

[29/Jan/2017 13:11:40] "GET /login/ HTTP/1.1" 200 18302

[29/Jan/2017 13:11:42] "POST /login/ HTTP/1.1" 302 0

AwardPrivateRoomPageView.get_context_data
[29/Jan/2017 13:11:43] "GET /account/private_room/ HTTP/1.1" 200 48343


Попадаю на страницу пользователя. Все нормально. Перехожу на страницу выбора конкурсов.

AwardMemberChooseAwardPageView.get_queryset
[29/Jan/2017 13:12:20] "GET /account/choose_award/ HTTP/1.1" 200 22897

Выбираю другой конкурс - №2

AwardMemberStoreAwardPageView.get_redirect_url
[29/Jan/2017 13:12:55] "GET /account/choose_award/2/ HTTP/1.1" 301 0
AwardPrivateRoomPageView.get_context_data
[29/Jan/2017 13:12:55] "GET /account/private_room/ HTTP/1.1" 200 36569


Все работает - открывается страница с данными по конкурсу №2.
Опять перехожу на страницу выбора конкурсов и выбираю конкурс №1.

AwardMemberChooseAwardPageView.get_queryset
[29/Jan/2017 13:13:08] "GET /account/choose_award/ HTTP/1.1" 200 22807
AwardMemberStoreAwardPageView.get_redirect_url
[29/Jan/2017 13:13:11] "GET /account/choose_award/1/ HTTP/1.1" 301 0
AwardPrivateRoomPageView.get_context_data
[29/Jan/2017 13:13:11] "GET /account/private_room/ HTTP/1.1" 200 47794


Опять все работает. Мы на странице с данными конкурса №1.
Снова перехожу на страницу выбора конкурсов, выбираю конкурс №2.

AwardMemberChooseAwardPageView.get_queryset
[29/Jan/2017 13:13:23] "GET /account/choose_award/ HTTP/1.1" 200 22897
AwardPrivateRoomPageView.get_context_data
[29/Jan/2017 13:13:38] "GET /account/private_room/ HTTP/1.1" 200 47794


И вот тут происходит сбой. Пользователь попадает на страницу с данными конкурса №1.
Получается, сам переход выполняется - но нет вызова метода AwardMemberStoreAwardPageView.get_redirect_url .
Повторные подобные манипуляции ничего не меняют.
Если пользователь выйдет из текущей сессии и заново зарегистрируется - ситуация повторяется аналогично описанному выше.

Кто-то с подобным сталкивался?
  • Вопрос задан
  • 444 просмотра
Решения вопроса 1
beugene
@beugene Автор вопроса
Oracle Developer, Delphi, Python, Django
Как оказалось нужно было правильно установить атрибут permanent класса RedirectView.
При установке в False сервер посылает код 302, а при True - код 301.
Значение этого атрибута влияет на то, откуда броузер берет данные - от сервера или из кэша.

class AwardMemberStoreAwardPageView(RedirectView):
    permanent = False
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы