I'm attempting to follow the following tutorial for pagination with django filters, but the tutorial seems to be missing something, and i'm unable to get the pagination to show using the function based views method.
https://simpleisbetterthancomplex.com/tutorial/2016/08/03/how-to-paginate-with-django.html
My updated users_list.html is the following:
{% extends 'base.html' %}
{% load widget_tweaks %}
{% block content %}
<form method="get">
<div class="well">
<h4 style="margin-top: 0">Filter</h4>
<div class="row">
<div class="form-group col-sm-4 col-md-4">
<label/> 3-4 User ID
{% render_field filter.form.employeentname class="form-control" %}
</div>
<div class="form-group col-sm-4 col-md-4">
<label/> First Name
{% render_field filter.form.employeefirstname class="form-control" %}
</div>
<div class="form-group col-sm-4 col-md-4">
<label/> Last Name
{% render_field filter.form.employeelastname class="form-control" %}
</div>
<div class="form-group col-sm-4 col-md-4">
<label/> Status
{% render_field filter.form.statusid class="form-control" %}
</div>
<div class="form-group col-sm-4 col-md-4">
<label/> Title
{% render_field filter.form.positiondesc class="form-control" %}
</div>
</div>
<button type="submit" class="btn btn-primary">
<span class="glyphicon glyphicon-search"></span> Search
</button>
</div>
</form>
<form action = "{% url 'results' %}" form method = "POST">
{% csrf_token %}
<table class="table table-bordered">
{{ form.as_table }}
<thead>
<tr>
<th>3-4</th>
<th>First name</th>
<th>Last name</th>
<th>Title</th>
<th>Status</th>
<th></th>
</tr>
</thead>
<tbody>
{% for user in filter.qs %}
<tr>
<td>{{ user.employeentname }}</td>
<td>{{ user.employeefirstname }}</td>
<td>{{ user.employeelastname }}</td>
<td>{{ user.positiondesc }}</td>
<td>{{ user.statusid }}</td>
<td><input type="checkbox" name="usercheck" value = "{{user.employeentname}}" /> </td>
</tr>
{% empty %}
<tr>
<td colspan="5">No data</td>
</tr>
{% endfor %}
</tbody>
</table>
<button class="btn btn-primary" type="submit">Select User</button>
</form>
{% endblock %}
My view below is based on the tutorial, but i'm using my own model:
def user_list(request):
user_list = Employee.objects.all()
user_filter = UserFilter(request.GET, queryset=user_list)
user_list = user_filter.qs
page = request.GET.get('page', 1)
paginator = Paginator(user_list.qs, 10)
try:
users = paginator.page(page)
except PageNotAnInteger:
users = paginator.page(1)
except EmptyPage:
users = paginator.page(paginator.num_pages)
args = {'filter':user_filter, 'users':users}
return render(request, 'user_list.html', args)
My directory structure is setup as the following, perhaps its something with that:
from django import forms
from .models import Employee
import django_filters
class UserFilter(django_filters.FilterSet):
class Meta:
model = Employee
fields = ['employeentname', 'employeefirstname', 'employeelastname', 'statusid', 'positiondesc']
def __init__(self, *args, **kwargs):
super(UserFilter, self).__init__(*args, **kwargs)
# at sturtup user doen't push Submit button, and QueryDict (in data) is empty
if self.data == {}:
self.queryset = self.queryset.none()
Added my base.html after moving pagination there:
{% load static %}<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="{% static 'css/bootstrap.min.css' %}" rel="stylesheet">
<!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/html5shiv/3.7.3/html5shiv.min.js"></script>
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
<![endif]-->
<style type="text/css">
.page-header {
margin-top: 0;
}
</style>
</head>
<body>
{% include 'includes/header.html' %}
<div class="container">
{% block content %}
{% if users.has_other_pages %}
<ul class="pagination">
{% if users.has_previous %}
<li><a href="?page={{ users.previous_page_number }}">«</a></li>
{% else %}
<li class="disabled"><span>«</span></li>
{% endif %}
{% for i in users.paginator.page_range %}
{% if users.number == i %}
<li class="active"><span>{{ i }} <span class="sr-only">(current)
</span></span></li>
{% else %}
<li><a href="?page={{ i }}">{{ i }}</a></li>
{% endif %}
{% endfor %}
{% if users.has_next %}
<li><a href="?page={{ users.next_page_number }}">»</a></li>
{% else %}
<li class="disabled"><span>»</span></li>
{% endif %}
</ul>
{% endif %}
{% endblock %}
</div>
<script src="{% static 'js/jquery-3.1.1.min.js' %}"></script>
<script src="{% static 'js/bootstrap.min.js' %}"></script>
{% block javascript %}
{% endblock %}
</body>
</html>
What i'm expecting is for my filter to paginate the search results for every 10 users. What i'm getting now is the entire set of users. The filter works correctly, it's the pagination that isn't.
You can paginate like this:
Note: user_filter.qs has filtered results and user_filter.queryset has unfiltered results
views.py
def search(request):
user_list = Employee.objects.all()
user_filter = UserFilter(request.GET, queryset=user_list)
user_list = user_filter.qs
paginator = Paginator(user_list, 10)
page = request.GET.get('page', 1)
try:
users = paginator.page(page)
except PageNotAnInteger:
users = paginator.page(1)
except EmptyPage:
users = paginator.page(paginator.num_pages)
args = {'paginator': paginator,'filter':user_filter,
'users':users,}
return render(request, 'search/user_list.html', args)
And then in the template:
{% for user in users %}
<tr>
<td>{{ user.employeeusername }}</td>
<td>{{ user.employeefirstname }}</td>
<td>{{ user.employeelastname }}</td>
<td>{{ user.statusid }}</td>
<td><input type="checkbox" name="usercheck" /> </td>
</tr>
{% empty %}
<tr>
<td colspan="5">No data</td>
</tr>
{% endfor %}
</tbody>
{% if users.has_other_pages %}
<ul class="pagination">
{% if users.has_previous %}
<li><a href="?page={{ users.previous_page_number }}">«</a></li>
{% else %}
<li class="disabled"><span>«</span></li>
{% endif %}
{% for i in users.paginator.page_range %}
{% if users.number == i %}
<li class="active"><span>{{ i }} <span class="sr-only">(current)
</span></span></li>
{% else %}
<li><a href="?page={{ i }}">{{ i }}</a></li>
{% endif %}
{% endfor %}
{% if users.has_next %}
<li><a href="?page={{ users.next_page_number }}">»</a></li>
{% else %}
<li class="disabled"><span>»</span></li>
{% endif %}
</ul>
I have tested it right now!It works fine for me.Just sharing a portion of the template with a view like the previous answer
<div class="row">
<div class="form-group col-sm-4 col-md-3">
{{ filter.form.row_date.label_tag }}
{% render_field filter.form.row_date class="form-control" %}
</div>
<div class="form-group col-sm-4 col-md-3">
{{ filter.form.director.label_tag }}
{% render_field filter.form.director class="form-control" %}
</div>
<div class="form-group col-sm-8 col-md-6">
{{ filter.form.manager.label_tag }}
{% render_field filter.form.manager class="form-control" %}
</div>
<div class="form-group col-sm-8 col-md-6">
{{ filter.form.analyst.label_tag }}
{% render_field filter.form.analyst class="form-control" %}
</div>
<div class="form-group col-sm-8 col-md-6">
<button type="submit" class="btn btn-primary">
<span class="glyphicon glyphicon-search"></span> Search
</button>
</div>
</div>
</div>
</div>
</form>
<table class="table table-bordered" >
<thead>
<tr>
<th>row_date</th>
<th>Director</th>
<th>Manager</th>
<th>Analyst</th>
</tr>
</thead>
<tbody>
{% for a in users %}
<tr>
<td>{{ a.row_date }}</td>
<td>{{ a.director }}</td>
<td>{{ a.manager }}</td>
<td>{{ a.analyst }}</td>
<td colspan="5">No data</td>
</tr>
{% empty %}
<tr>
<td colspan="5">No data</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% block javascript %}
<script src="{% static 'search/js/jquery-3.1.1.min.js' %}"></script>
<script src="{% static 'search/js/bootstrap.min.js' %}"></script>
{% endblock %}
</body>
</html>
I have written a post on implementing pagination with Django with function based view on my blog, you can check here
I have discussed several ways to implement pagination in Django
It's working fine for me. And if still, it's not working out for you, It's better to save time and try other alternatives.
Here are some suggestions:
1.Please try Q objects
2.You can do a lot with kwargs
3.Django REST Framework Filtering
4.For search-engine like capability haystack is a beast - maybe a bit complicated for a newbie.
5.You can also use Elastic Search.
Views.py
def avail_list(request):
avails1 = AvailstaticCopy.objects.all().order_by('-row_date')
avail_filter = AvailFilter(request.GET, queryset=avails1)
avails1 = avail_filter.qs
paginator = Paginator(avails1, 144)
page = request.GET.get('page',1)
try:
users = paginator.page(page)
except PageNotAnInteger:
users = paginator.page(1)
except EmptyPage:
users = paginator.page(paginator.num_pages)
context = {
'paginator': paginator,
'users': users,
'filter': avail_filter,
}
return render(request,'avails/avail_list.html',context)
A Portion of the template for reference with a situation similar to the question:
<div class="row">
<div class="form-group col-sm-4 col-md-3">
{{ filter.form.row_date.label_tag }}
{% render_field filter.form.row_date class="form-control" %}
</div>
<div class="form-group col-sm-4 col-md-3">
{{ filter.form.director.label_tag }}
{% render_field filter.form.director class="form-control" %}
</div>
<div class="form-group col-sm-8 col-md-6">
{{ filter.form.manager.label_tag }}
{% render_field filter.form.manager class="form-control" %}
</div>
<div class="form-group col-sm-8 col-md-6">
{{ filter.form.analyst.label_tag }}
{% render_field filter.form.analyst class="form-control" %}
</div>
<div class="form-group col-sm-8 col-md-6">
<button type="submit" class="btn btn-primary">
<span class="glyphicon glyphicon-search"></span> Search
</button>
</div>
</div>
</div>
</div>
<table class="table table-bordered" >
<thead>
<tr>
<th>row_date</th>
<th>Director</th>
<th>Manager</th>
<th>Analyst</th>
</tr>
</thead>
<tbody>
{% for a in users %}
<tr>
<td>{{ a.row_date }}</td>
<td>{{ a.director }}</td>
<td>{{ a.manager }}</td>
<td>{{ a.analyst }}</td>
</tr>
{% empty %}
<tr>
<td colspan="5">No data</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% block javascript %}
<script src="{% static 'search/js/jquery-3.1.1.min.js' %}"></script>
<script src="{% static 'search/js/bootstrap.min.js' %}"></script>
{% endblock %}
</body>
</html>
I don't know if this is relevant but it seems to me that the issue may be where you are setting the paginator. In your view you have
paginator = Paginator(user_list.qs, 10)
but if you look closely at the solutions provided they are suggesting that you should be using
paginator = Paginator(user_list, 10)
ie without .qs as you've already defined user_list in a previous line with user_list = user_filter.qs
来源:https://stackoverflow.com/questions/48546864/django-filter-with-pagination