Django pagination выбрасывает ошибку при попытке перейти на следующую страницу

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

У меня есть HomeView, который наследует ListView, где у меня есть paginate_by = 30, и он отображается на главной странице и работает так, как должен, в плане перехода на любую страницу, на которую я нажимаю.

У меня есть другое представление под названием NegotiableAdView, которое также наследует ListView. В этом представлении я получаю значение из request.GET, которое является либо yes, либо no, затем фильтрую набор запросов соответствующим образом для возврата. Он отображает количество объявлений, для которых я установил атрибут paginate_by, но проблема в том, что всякий раз, когда я нажимаю на page 2 или любой другой номер страницы, он говорит, например, следующее:

Страница не найдена (404)... Неверная страница (2): Эта страница не содержит результатов

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

Внутри файла html, содержащего форму:

<form method="GET" action="{% url 'store:search-negotiation' %}">
     <div id="collapseThreee" class="panel-collapse collapse " role="tabpanel" aria-labelledby="headingThreee">
          <div class="panel-body">
               <div class="skin-minimal">
                    <ul class="list">
                         <li>
                              <input type="radio" id="radio-yes" name="negotiable" value="Yes">
                              <label for="yes">Yes</label>
                         </li>
                         <li>
                              <input type="radio" id="radio-no" name="negotiable" value="No">
                              <label for="no">No</label>
                         </li>
                    </ul>
               </div>
          </div>
     </div>
</form>

Внутри файла urls.py:

from .views import NegotiableAdView

app_name = 'store'

urlpatterns = [
    ...
    path('search-negotiation/', NegotiableAdView.as_view(), name='search-negotiation'),
    ...
]

Внутри файла views.py:

class NegotiableAdView(ListView):
     context_object_name = 'ads'
     paginate_by = 12
     template_name = 'store/pages/results.html'

     def get_queryset(self, *args, **kwargs):
          negotiable = self.request.GET.get('negotiable')

          queryset = Advertisement.objects.filter(negotiable__iexact=negotiable).order_by('-publish', 'name')

          return queryset

     def get_context_data(self, **kwargs):
          context = super().get_context_data(**kwargs)
          negotiable = self.request.GET.get('negotiable')

          # This 'negotiable' var is only not none when on the first page of the results
          if negotiable:
               context['result_name'] = f'Results "{negotiable.title()}"'

          return context

Внутри файла results.html, который включает pagination:

{% for ad in ads %}
    ...
{% endfor %}


{% include 'store/includes/pagination.html' with pages=page_obj %}

Внутри файла pagination.html:

{% if is_paginated %}
    <ul class="pagination pagination-lg">
        {% if pages.has_previous %}
            <li>
                <a href="?page={{ pages.previous_page_number }}">« Previous Page</a>
            </li>
        {% endif %}

        {% if pages.number|add:'-4' > 1 %}
            <li>
                <a href="?page={{ pages.number|add:'-5' }}">&hellip;</a>
            </li>
        {% endif %}

        {% for number in pages.paginator.page_range %}
            {% if pages.number == number %}
                <li class="active">
                    <a href="javascript:void(0);">{{ number }}</a>
                </li>
            {% elif number > pages.number|add:'-5' and number < pages.number|add:'5' %}
                <li>
                    <a href="?page={{ number }}">{{ number }}</a>
                </li>
            {% endif %}
        {% endfor %}

        {% if pages.paginator.num_pages > pages.number|add:'4' %}
            <li>
                <a href="?page={{ pages.number|add:'5' }}">&hellip;</a>
            </li>
        {% endif %}

        {% if pages.has_next %}
            <li>
                <a href="?page={{ pages.next_page_number }}">Next Page »</a>
            </li>
        {% endif %}
    </ul>
{% endif %}

Также следует отметить, что на странице результатов, если пользователь выбирает urlyes, . Но когда пользователь нажимает на http://127.0.0.1:8000/search-negotiation/?negotiable=Yes, например, я вижу page 2 с отображением ошибки, как указано ранее.http://127.0.0.1:8000/search-negotiation/?page=2

Может ли кто-нибудь указать, что я делаю неправильно, пожалуйста? Любая помощь будет очень признательна.

Итак, у меня появилась идея, я попробовал ее, и она сработала! Я предполагаю, что это может быть не самый эффективный способ решения конкретной проблемы, но вот что я сделал.

Итак, я создал новый url в url.py файле.

 urlpatterns = [
      ...
      path('search/', RedirectedSearchView.as_view(), name='search'), # new url
      path('search-negotiation/<str:negotiable>/', NegotiableAdView.as_view(), name='search-negotiation'), # update this url for kwargs.
      ...
 ]

Форма отправит запрос GET для обработки на новый url, где он также будет перенаправлен соответствующим образом.

Форма:

<form method="GET" action="{% url 'store:search' %}"> <!-- updated url here -->
     <div id="collapseThreee" class="panel-collapse collapse " role="tabpanel" aria-labelledby="headingThreee">
          <div class="panel-body">
               <div class="skin-minimal">
                    <ul class="list">
                         <li>
                              <input type="radio" id="radio-yes" name="negotiable" value="Yes">
                              <label for="yes">Yes</label>
                         </li>
                         <li>
                              <input type="radio" id="radio-no" name="negotiable" value="No">
                              <label for="no">No</label>
                         </li>
                    </ul>
               </div>
          </div>
     </div>
</form>

Внутри файла views.py:

# This view will handle the GET request and then redirect to the necessary view.
class RedirectedSearchView(TemplateView):
     def get(self, request, *args, **kwargs):
          # Doing a check here to see if the form made a GET request by trying to get a value submitted
          if request.GET.get('negotiable'):
               # As I do the redirect, I must pass a 'negotiable' value to the url
               # Assigning the value passed from the request.GET -> negotiable=request.GET.get('negotiable').lower()

               return redirect('store:search-negotiation', negotiable=request.GET.get('negotiable').lower())

          return redirect('store:home')

class NegotiableAdView(ListView):
     context_object_name = 'ads'
     paginate_by = 12
     template_name = 'store/pages/results.html'

     def get_queryset(self, *args, **kwargs):
          # Collecting the value from the url to filter the queryset to return
          negotiable = self.kwargs.get('negotiable', '')

          return Advertisement.objects.filter(negotiable__iexact=negotiable).order_by('-publish', 'name')

 def get_context_data(self, **kwargs):
      context = super().get_context_data(**kwargs)
      negotiable = self.kwargs.get('negotiable', '')

      context['result_name'] = f'Results "{negotiable.title()}"'

      return context

После того, как я сделал это таким образом, мой pagination теперь переходит на другие страницы, как он не делал раньше.

Как я уже сказал, это решение может быть не самым эффективным. Поэтому я открыт для получения чего-то более эффективного и правильного.

Заранее спасибо!

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