Django 3.1搜索分页第二页及以后空白问题求助
Absolutely, the missing keywords parameter in your pagination URLs is exactly why the second page (and beyond) shows up blank! Let me break down the problem and fix it for you:
Why This Happens
When you click a pagination link, your current code only adds the page parameter to the URL, but it doesn't carry over the original keywords parameter. So when the view receives the request for ?page=2, there's no keywords in request.GET—it hits the else branch and returns the empty search page instead of filtered results.
Fix 1: Quick & Simple (Pass Keywords Directly)
The easiest fix is to modify your template pagination links to include the keywords value from the original request. Update your HTML code like this:
<div class="col-md-12"> {% if queries.has_other_pages %} <ul class="pagination"> {% if queries.has_previous %} <li class="page-item"> <a href="?keywords={{ request.GET.keywords }}&page={{ queries.previous_page_number }}" class="page-link">«</a> </li> {% else %} <li class="page-item disabled"> <a class="page-link">«</a> </li> {% endif %} {% for i in queries.paginator.page_range %} {% if queries.number == i %} <li class="page-item active"> <a class="page-link">{{i}}</a> </li> {% else %} <li class="page-item"> <a href="?keywords={{ request.GET.keywords }}&page={{i}}" class="page-link">{{i}}</a> </li> {% endif %} {% endfor %} {% if queries.has_next %} <li class="page-item"> <a href="?keywords={{ request.GET.keywords }}&page={{ queries.next_page_number }}" class="page-link">»</a> </li> {% else %} <li class="page-item disabled"> <a class="page-link">»</a> </li> {% endif %} </ul> {% endif %} </div>
Fix 2: Robust & Scalable (Preserve All Query Params)
If you ever add more search filters (like category, date ranges, etc.), the above method will fail to carry those over. A better approach is to preserve all existing query parameters except the page value:
- Update your
views.pyto pass cleaned query parameters to the template:
def search(request): # Keywords if 'keywords' in request.GET: keywords = request.GET['keywords'] if keywords: # Use Q objects for cleaner, database-level filtering (avoids memory-heavy deduping) from django.db.models import Q result_list_control_valves = queryset_list.filter( Q(title__icontains=keywords) | Q(description__icontains=keywords) ).distinct().order_by('title') paginator = Paginator(result_list_control_valves, 1) page = request.GET.get('page') paged_queries = paginator.get_page(page) # Preserve all query params except 'page' query_params = request.GET.copy() query_params.pop('page', None) context = { 'queries': paged_queries, 'query_params': query_params.urlencode() } return render(request, 'pages/search.html', context) else: return render(request, 'pages/search.html') else: return render(request, 'pages/search.html')
- Update your template to use these preserved parameters:
<div class="col-md-12"> {% if queries.has_other_pages %} <ul class="pagination"> {% if queries.has_previous %} <li class="page-item"> <a href="?{{ query_params }}&page={{ queries.previous_page_number }}" class="page-link">«</a> </li> {% else %} <li class="page-item disabled"> <a class="page-link">«</a> </li> {% endif %} {% for i in queries.paginator.page_range %} {% if queries.number == i %} <li class="page-item active"> <a class="page-link">{{i}}</a> </li> {% else %} <li class="page-item"> <a href="?{{ query_params }}&page={{i}}" class="page-link">{{i}}</a> </li> {% endif %} {% endfor %} {% if queries.has_next %} <li class="page-item"> <a href="?{{ query_params }}&page={{ queries.next_page_number }}" class="page-link">»</a> </li> {% else %} <li class="page-item disabled"> <a class="page-link">»</a> </li> {% endif %} </ul> {% endif %} </div>
Bonus: Optimize Your Search Logic
Your original code uses chain and dict.fromkeys to combine and deduplicate results, which pulls all matching records into memory first. Using Django's Q objects lets the database handle filtering and deduplication directly—this is faster, more efficient, and cleaner.
Why This Works
Now when you click a pagination link, the URL will include both the keywords parameter (and any future filters you add) along with the page number. Your view will receive the keywords again, re-run the search, and return the correct page of results.
内容的提问来源于stack exchange,提问作者Shahriar.M

