Показывать действительные номера страниц, когда номер текущей страницы выходит за пределы диапазона - PullRequest
0 голосов
/ 21 мая 2019

У Django есть проблема с нумерацией страниц по умолчанию ListView, заключающаяся в том, что при доступе к представлению списка с номером страницы, выходящим за пределы диапазона, что обычно может произойти, когда я обновляю последнюю страницу, когда некоторые объекты удаляются, поэтому общее количество страниц уменьшается, Django выдаст ошибку 404.

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

Так вот мой код

from django.views.generic import ListView
from django.shortcuts import render
from django.http import Http404

class MyListView(ListView):
    def get(self, request, *args, **kwargs):
        try:
            return super().get(request, *args, **kwargs)
        except Http404:
            return render(request, 'pagenum_out_of_range.html', status=404)

    model = MyModel
    context_object_name = 'my_models'
    template_name = 'my_models_list.html'
    paginate_by = 20

и pagenum_out_of_range.html

{% extends my_project_base_template %}

{% block body %}
    <p>Invalid page number and there's no result here. Please try somewhere else.</p>

    {% for object in page_obj.paginator.page_range %}
        <a class="page-link" href="?page={{ forloop.counter }}">{{ forloop.counter }}</a>
    {% endfor %}
{% endblock %}

Но это не работает (ссылки не отображаются). Я думаю, что это потому, что я не прошел контекст, поэтому я изменил последнюю строку выше на

return render(request, 'pagenum_out_of_range.html', status=404,
              context=self.get_context_data())

Однако снова появляется ошибка 404 по умолчанию.

Я совершенно запутался по этому поводу. Какой правильный подход?


UPDATE

Очень ценю ваши предложения, и я провел больше исследований и отладок по этому вопросу.

Я попытался переопределить еще несколько методов, упомянутых в Блок-схема метода ListView , чтобы посмотреть, смогу ли я изменить поведение программы или получить некоторые промежуточные результаты.

class MyListView(ListView):
    # ...


    def get_context_data(self, **kwargs):
        print('>>>> get_context_data called')
        r = super().get_context_data(**kwargs)
        print('>>>> get_context_data return:', r)
        return r

    def get_template_names(self):
        print('>>>> get_template_names called')
        r = super().get_template_names()
        print('>>>> get_template_names return:', r)
        return r

    def render_to_response(self, context, **response_kwargs):
        print('>>>> render_to_response called')
        r = super().render_to_response(context, **response_kwargs)
        print('>>>> render_to_response return:', r)
        return r

Когда я обновляю страницу, я вижу следующий вывод

>>>> get_context_data called
>>>> get_context_data called

Похоже, что get_context_data прервано каким-то исключением, и это исключение Http404 поднято с MultipleObjectMixin.paginate_queryset, как я проследил. Я думаю, это то, где я должен исправить.

Меня беспокоит, что я не могу найти официальную документацию о paginate_queryset, поэтому я не совсем уверен, что это правильный путь.

1 Ответ

0 голосов
/ 21 мая 2019

Я думаю, вы можете сделать это, переопределив метод get_template_names.Кроме того, поступая таким образом, я не думаю, что вам нужно переопределять метод get.

class MyListView(ListView):
    model = MyModel
    context_object_name = 'my_models'
    default_template_name = 'my_models_list.html'
    error_template_name = 'pagenum_out_of_range.html'
    paginate_by = 20

    def get_template_names(self):
        if self.request.status_code == 404:
            return [self.error_template_name]
        else:
            return [self.default_template_name]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...