尝试转到下一页时 Django 分页抛出错误

Django pagination throwing an error when trying to go to the next page

我目前正在从事一个将在网站上显示广告的项目。即使在研究半天试图找到解决方案但没有运气之后,我仍面临一定程度的困难。

我有一个 HomeView 它继承了 ListView 我有 paginate_by = 30 的地方,它显示在主页上,并且在转到我的任何页码方面都可以正常工作点击。

我有另一个名为 NegotiableAdView 的视图,它也继承了 ListView。在这个视图中,我从 request.GET 得到一个值,它是 yes no 然后根据 return 过滤查询集。它显示我将 paginate_by 属性设置为的广告数量,但问题是每当我点击 page 2 或它说的任何页码时,例如:

Page not found (404)... Invalid page (2): That page contains no results

我不确定为什么会出现该错误。但是我有没有以下...

在包含以下形式的 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

在包含 pagination:

results.html 文件中
{% 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 %}

还要注意,如果用户选择 yeshttp://127.0.0.1:8000/search-negotiation/?negotiable=Yes,结果页面上的 url .但是,例如,当用户单击 page 2 时,我看到 http://127.0.0.1:8000/search-negotiation/?page=2 并显示如前所述的错误。

有人可以指出我做错了什么吗?任何帮助将不胜感激。

所以我有了一个想法,尝试了一下,结果成功了!我认为这可能不是解决我遇到的特定问题的最有效方法,但我就是这样做的。

因此,我在 url.py 文件中创建了一个新的 url

 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 现在可以转到其他页面,因为它以前不会这样做。

如我所说,此解决方案可能不是最有效的解决方案。因此,我愿意接受更有效和正确的方法。

提前致谢!