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' }}">…</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' }}">…</a>
</li>
{% endif %}
{% if pages.has_next %}
<li>
<a href="?page={{ pages.next_page_number }}">Next Page »</a>
</li>
{% endif %}
</ul>
{% endif %}
Также следует отметить, что на странице результатов, если пользователь выбирает url
yes, . Но когда пользователь нажимает на 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
теперь переходит на другие страницы, как он не делал раньше.
Как я уже сказал, это решение может быть не самым эффективным. Поэтому я открыт для получения чего-то более эффективного и правильного.
Заранее спасибо!