Django分页功能中用户自定义每页显示条数失效问题求助
Hey there! Let's fix that custom per-page count issue you're having. The problem boils down to a few small gaps in how your form submits data and how your pagination links preserve the selected per-page value. Here's how to get it working:
1. Fix the per_page handling in views.py
Right now, you're grabbing per_page as an unvalidated string and falling back to 1 (which is probably not your intended default). Let's clean up the logic to handle validation, type conversion, and sensible defaults:
def finished_ads_view(request): queryset = Campaign.objects.filter(completion_percent=100) # Handle per_page with validation and reasonable default try: per_page = int(request.GET.get('dropdown', 10)) # Default to 10 if no input # Restrict to allowed values to prevent weird user inputs via URL if per_page not in [1, 2, 15, 20, 25]: per_page = 10 except ValueError: # Catch non-integer values and use default per_page = 10 page = request.GET.get('page', 1) paginator = Paginator(queryset, per_page) try: posts = paginator.page(page) except PageNotAnInteger: posts = paginator.page(1) except EmptyPage: posts = paginator.page(paginator.num_pages) context = { 'posts': posts, 'current_per_page': per_page, # Pass current value to template for dropdown state } return render(request, 'finished_campaigns.html', context)
Key changes here:
- Use
request.GET.get()instead of direct indexing to avoidKeyErrorwhen the parameter is missing - Convert the value to an integer (since
Paginatorexpects a numeric value) - Add a check to ensure the value is one of your allowed options
- Pass
current_per_pageto the template so we can keep the dropdown synced with the user's selection
2. Fix the template form and pagination links
Your form wasn't properly configured to submit via GET (matching how your view reads parameters), and pagination links didn't carry over the selected per-page value—so switching pages reset to the default. Here's the updated template code:
<!-- Wrap dropdown/submit in a GET form to pass parameters correctly --> <form method="get" class="mb-3"> <select name="dropdown" class="form-select d-inline-block w-auto"> {% for option in [1,2,15,20,25] %} <option value="{{ option }}" {% if current_per_page == option %}selected{% endif %}> {{ option }} </option> {% endfor %} </select> <input type="submit" value="Update Page Size" class="btn btn-primary ms-2"/> </form> <nav aria-label="Page navigation"> <ul class="pagination justify-content-center"> {% if posts.has_previous %} <li class="page-item"> <a class="page-link" href="?page=1&dropdown={{ current_per_page }}" aria-label="Previous"> <span aria-hidden="true">«</span> <span class="sr-only">begin</span> </a> </li> {% endif %} {% for n in posts.paginator.page_range %} {% if posts.number == n %} <li class="page-item active"> <span class="page-link">{{ n }}<span class="sr-only">(current)</span></span> </li> {% elif n > posts.number|add:'-3' and n < posts.number|add:'3' %} <li class="page-item"> <a class="page-link" href="?page={{ n }}&dropdown={{ current_per_page }}">{{ n }}</a> </li> {% endif %} {% endfor %} {% if posts.has_next %} <li class="page-item"> <a class="page-link" href="?page={{ posts.paginator.num_pages }}&dropdown={{ current_per_page }}" aria-label="Next"> <span aria-hidden="true">»</span> <span class="sr-only">end</span> </a> </li> {% endif %} </ul> </nav>
Key template fixes:
- Added a
<form>tag withmethod="get"to ensure the dropdown value is submitted correctly - Updated the dropdown to loop through allowed options and mark the current selection as
selected - Added
&dropdown={{ current_per_page }}to all pagination links, so the selected page size persists when navigating between pages
Why this works:
- The view now properly validates and converts the per-page value, with a sensible default
- The form submits the user's choice via GET, which matches how your view retrieves parameters
- All pagination links carry over the selected page size, so users don't lose their preference when switching pages
内容的提问来源于stack exchange,提问作者low_ratio

