django-filter 使用分页
django-filter use paginations
我正在使用 django-filter
包在我的列表视图中提供搜索功能。
现在我也想为该视图添加分页。
我正在尝试将分页与过滤查询集相结合,但我不知道如何继续。
到目前为止,我已经在 views.py
上尝试了以下操作:
def search(request):
qs = local_url.objects.filter(global_url__id=1).all()
paginator = Paginator(qs, 25)
page = request.GET.get('page')
try:
pub = paginator.page(page)
except PageNotAnInteger:
pub = paginator.page(1)
except EmptyPage:
pub = paginator.page(paginator.num_pages)
url_filter = PublicationFilter(request.GET, queryset=qs)
return render(request, 'ingester/search_list.html', {'filter': url_filter, 'publication':pub})
据我了解,您的目标是对过滤后的查询集进行分页。如果是这样,您可以将 PublicationFilter 对象的 "qs" 属性 传递给 Paginator 构造函数:
def search(request):
qs = local_url.objects.filter(global_url__id=1).all()
url_filter = PublicationFilter(request.GET, queryset=qs)
paginator = Paginator(url_filter.qs, 25)
page = request.GET.get('page')
try:
pub = paginator.page(page)
except PageNotAnInteger:
pub = paginator.page(1)
except EmptyPage:
pub = paginator.page(paginator.num_pages)
url_filter = PublicationFilter(request.GET, queryset=qs)
return render(request, 'ingester/search_list.html', {'publication':pub})
url_filter.qs 包含筛选的查询集
url_filter.queryset 包含未过滤的查询集
要使用 Django 过滤器并对过滤结果进行分页,您可以执行以下操作:
为您的模型创建过滤器 class:
在 my_project/my_app/filters.py
:
import django_filters
class MyModelFilter(django_filters.FilterSet):
class Meta:
model = MyModel
# Declare all your model fields by which you will filter
# your queryset here:
fields = ['field_1', 'field_2', ...]
每个 FilterSet
对象都有一个 .qs
属性 其中包含 过滤查询集 你甚至可以 override it if you want.
我们将分页 .qs
属性 的 MyModelFilter
:
在 my_project/my_app/views.py
:
from . import filters
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
def my_view(request):
# BTW you do not need .all() after a .filter()
# local_url.objects.filter(global_url__id=1) will do
filtered_qs = filters.MyModelFilter(
request.GET,
queryset=MyModel.objects.all()
).qs
paginator = Paginator(filtered_qs, YOUR_PAGE_SIZE)
page = request.GET.get('page')
try:
response = paginator.page(page)
except PageNotAnInteger:
response = paginator.page(1)
except EmptyPage:
response = paginator.page(paginator.num_pages)
return render(
request,
'your_template.html',
{'response': response}
)
给你!
PS_1: 我的 Django 过滤器,"plays" better with Django Rest Framework.
PS_2: 如果你打算使用 DRF,我已经写了一个关于如何在基于函数的视图中使用分页的例子,你可以很容易地结合一个 FilterSet
:
@api_view(['GET',])
def my_function_based_list_view(request):
paginator = PageNumberPagination()
filtered_set = filters.MyModelFilter(
request.GET,
queryset=MyModel.objects.all()
).qs
context = paginator.paginate_queryset(filtered_set, request)
serializer = MyModelSerializer(context, many=True)
return paginator.get_paginated_response(serializer.data)
这对我有用:
在我的模板中而不是使用这个
<li><a href="?page={{ i }}">{{ i }}</a></li>
我写了这个:
{% if 'whatever_parameter_you_use_to_filter' in request.get_full_path %}
<li><a href="{{ request.get_full_path }}&page={{ i }}"{{ i }}</a></li>
{% else %}
<li><a href="?page={{ i }}">{{ i }}</a></li>
{% endif %}
希望对您有所帮助:)
这里最重要的部分是如何在模板中构建 URL。
你可能有
{% if pages.has_previous %}
<li><a href="?page={{ pages.previous_page_number }}">Prev</a></li>
{% endif %}
如果您仅使用它在初始分页结果之间切换,这非常好。
但棘手的部分是当您使用 django-fitler
过滤器时,查询字符串('?' 之后的那部分)变得全新 key-values对,忽略你的 ?page=2
或类似的。
因此,要使分页与过滤结果一起使用,当您单击 "Next" 或 "Prev" 按钮时 - 在 django-fitler
的 key-values 中,您还需要通过&page=5
一对。
如@stathoula 所述,您需要检查查询字符串中是否已存在至少一个过滤字段。如果是,那么您需要使用已经存在的 key-value 对,然后是新的 &page=3
对。
这看起来很简单,但我不得不做一些小技巧,不要在用户点击箭头时在查询字符串中一遍又一遍地重复 &page=1
。
在我的例子中,我将 'title' 作为过滤器,所以我需要检查它是否已经存在。
这是我为我的项目所做的完美工作的片段。
templates/pagination.html
<div class="paginator">
{% with request.get_full_path as querystring %}
<ul class="pagination nav navbar-nav">
<!-- Previous page section -->
{% if pages.has_previous %}
{% if 'title' in querystring %}
{% if 'page' in querystring %}
<li class="paginator {% if pages.number == page %}active{% endif %}">
<a href="{{ querystring|slice:":-7" }}&page={{ pages.previous_page_number }}">Prev</a>
</li>
{% else %}
<li class="paginator {% if pages.number == page %}active{% endif %}">
<a href="{{ querystring }}&page={{ pages.previous_page_number }}">Prev</a>
</li>
{% endif %}
{% else %}
<li class="paginator {% if pages.number == page %}active{% endif %}">
<a href="?page={{ pages.previous_page_number }}">Prev</a>
</li>
{% endif %}
{% endif %}
<!-- All pages section -->
{% for page in pages.paginator.page_range %}
{% if 'title' in querystring %}
{% if 'page' in querystring %}
<li class="paginator {% if pages.number == page %}active{% endif %}">
<a href="{{ querystring|slice:":-7" }}&page={{ page }}">{{ page }}</a>
</li>
{% else %}
<li class="paginator {% if pages.number == page %}active{% endif %}">
<a href="{{ querystring }}&page={{ page }}">{{ page }}</a>
</li>
{% endif %}
{% else %}
<li class="paginator {% if pages.number == page %}active{% endif %}">
<a href="?page={{ page }}">{{ page }}</a>
</li>
{% endif %}
{% endfor %}
<!-- Next page section -->
{% if pages.has_next %}
{% if 'title' in querystring %}
{% if 'page' in querystring %}
<li class="paginator {% if pages.number == page %}active{% endif %}">
<a href="{{ querystring|slice:":-7" }}&page={{ pages.next_page_number }}">Next</a>
</li>
{% else %}
<li class="paginator {% if pages.number == page %}active{% endif %}">
<a href="{{ querystring }}&page={{ pages.next_page_number }}">Next</a>
</li>
{% endif %}
{% else %}
<li class="paginator {% if pages.number == page %}active{% endif %}">
<a href="?page={{ pages.next_page_number }}">Next</a>
</li>
{% endif %}
{% endif %}
</ul>
{% endwith %}
</div>
这里是视图,以防万一:
app/views.py
def index(request):
condo_list = Condo.objects.all().order_by('-timestamp_created')
condo_filter = CondoFilter(request.GET, queryset=condo_list)
paginator = Paginator(condo_filter.qs, MAX_CONDOS_PER_PAGE)
page = request.GET.get('page')
try:
condos = paginator.page(page)
except PageNotAnInteger:
condos = paginator.page(1)
except EmptyPage:
condos = paginator.page(paginator.num_pages)
return render(request, 'app/index.html', {
'title': 'Home',
'condos': condos,
'page': page,
'condo_filter': condo_filter,
})
这是一个工作示例:
.
为了增加答案,我还使用了 html 表以及 django-filters 和 Paginator。下面是我的视图和模板文件。需要模板标签以确保将正确的参数传递给分页 url.
search_view.py
from django.shortcuts import render
from app.models.filters_model import ApiStatusFilter
from app.models.api_status import ApiStatus
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from datetime import datetime, timedelta
def status(request):
all_entries_ordered = ApiStatus.objects.values().order_by('-created_at')[:200]
for dictionarys in all_entries_ordered:
dictionarys
apistatus_list = ApiStatus.objects.values().order_by('-created_at')
apistatus_filter = ApiStatusFilter(request.GET, queryset=apistatus_list)
paginator = Paginator(apistatus_filter.qs, 10)
page = request.GET.get('page')
try:
dataqs = paginator.page(page)
except PageNotAnInteger:
dataqs = paginator.page(1)
except EmptyPage:
dataqs = paginator.page(paginator.num_pages)
return render(request, 'status_page_template.html', {'dictionarys': dictionarys, 'apistatus_filter': apistatus_filter, 'dataqs': dataqs, 'allobjects': apistatus_list})
status_template.html
{% load static %}
{% load my_templatetags %}
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" type="text/css" href="{% static 'css/table_styling.css' %}">
<meta charset="UTF-8">
<title>TEST</title>
</head>
<body>
<table>
<thead>
<tr>
{% for keys in dictionarys.keys %}
<th>{{ keys }}</th>
{% endfor %}
</tr>
</thead>
<form method="get">
{{ apistatus_filter.form.as_p }}
<button type="submit">Search</button>
{% for user in dataqs.object_list %}
<tr>
<td>{{ user.id }}</td>
<td>{{ user.date_time }}</td>
<td>{{ user.log }}</td>
</tr>
{% endfor %}
</form>
</tbody>
</table>
<div class="pagination">
<span>
{% if dataqs.has_previous %}
<a href="?{% query_transform request page=1 %}">« first</a>
<a href="?{% query_transform request page=dataqs.previous_page_number %}">previous</a>
{% endif %}
<span class="current">
Page {{ dataqs.number }} of {{ dataqs.paginator.num_pages }}.
</span>
{% if dataqs.has_next %}
<a href="?{% query_transform request page=dataqs.next_page_number %}">next</a>
<a href="?{% query_transform request page=dataqs.paginator.num_pages %}">last »</a>
{% endif %}
</span>
</div>
</body>
</html>
my_templatetags.py
from django import template
register = template.Library()
@register.simple_tag
def query_transform(request, **kwargs):
updated = request.GET.copy()
for k, v in kwargs.items():
if v is not None:
updated[k] = v
else:
updated.pop(k, 0)
return updated.urlencode()
我花了一些时间才找到 DRYer 和更清洁的解决方案来解决这个问题,我认为最好的解决方案是使用模板标签的解决方案。
from django import template
register = template.Library()
@register.simple_tag
def relative_url(value, field_name, urlencode=None):
url = '?{}={}'.format(field_name, value)
if urlencode:
querystring = urlencode.split('&')
filtered_querystring = filter(lambda p: p.split('=')[0] != field_name, querystring)
encoded_querystring = '&'.join(filtered_querystring)
url = '{}&{}'.format(url, encoded_querystring)
return url
并在您的模板中
<a href="{% relative_url i 'page' request.GET.urlencode %}">{{ i }}</a>
- 简单又甜美,
- 使用这个,
pip install filter-and-pagination
- https://pypi.org/project/filter-and-pagination/
实施步骤
- 通过
pip install filter-and-pagination
安装包
- 通过
from filter_and_pagination import FilterPagination
在 view.py 中导入 FilterPagination
- 在您的函数中按照以下标准编写代码...
queryset = FilterPagination.filter_and_pagination(request, Customer)
serialize_data = CustomerSerializer(queryset['queryset'], many=True).data
resultset = {'dataset': serialize_data, 'pagination': queryset['pagination']}
- 在这段代码中
Customer
是Django模型&
CustomerSerializer
是一个 DRF 序列化器 class
- 在结果集中它包含数据集和分页数据,采用这种格式(API 响应)link:https://github.com/ashish1997it/filter-pagination-dj#demo
- 对于 API 请求,请遵循 PostMan collection link: https://github.com/ashish1997it/filter-pagination-dj#postman 在 header 部分,它将采用一个参数并请求您根据您的要求
如果您仍然遇到任何困难,请与我联系:)
我对分页结果“记住 filter/query URL 参数”的方法:将当前 URL 参数作为上下文变量传递:
# views.py
class PublicationFilterView(FilterView):
model = Publication
filterset_class = PublicationFilter
paginate_by = 15
def get_context_data(self, *args, **kwargs):
_request_copy = self.request.GET.copy()
parameters = _request_copy.pop('page', True) and _request_copy.urlencode()
context = super().get_context_data(*args, **kwargs)
context['parameters'] = parameters
return context
# templates/path/to/pagination.html
<a href="?page={{ page_obj.next_page_number }}&{{ parameters }}">
Next
</a>
这个对我来说 100% 有效
views.py:
def search(request):
category=Category.objects.all()
try:
qs=request.GET["qs"]
products=Product.objects.filter(Q(name__icontains=qs) |Q(details__icontains=qs) | Q(category__name__icontains=qs) | Q(branch__child__icontains=qs) | Q(manufacturer__name__icontains=qs) | Q(color__name__icontains=qs)).distinct()
print(products)
search=f"qs={qs}"
except:
search=None
并在 HTML
<ul class="shop-p__pagination">
{% if products.has_provious %}
<li>
<a class="fas fa-angle-left" href="?page={{ products.previous_page_number }}&{search}"></a></li>
{% endif %}
{% for i in products.paginator.page_range %}
{% if products.number == i %}
<li class="is-active"><a href="?page={{i}}&{{search}}">{{i}}</a></li>
{% else %}
<li><a href="?page={{i}}&{{search}}">{{i}}</a></li>
{% endif %}
{% endfor %}
{% if products.has_next %}
<li>
<a class="fas fa-angle-right" href="?page={{ products.next_page_number }}&{{search}}"></a></li>
{% endif %}
</ul>
在get_context_data()
函数中:
form_submitted = 'csrfmiddlewaretoken' in self.request.GET
context['cleaned_full_path'] = '{}{}'.format(
self.request.get_full_path().split('&page' if form_submitted else '?page')[0],
'&' if form_submitted else '?'
)
然后,在您的模板中,加载类似
的内容
<a href="{{ cleaned_full_path }}page={{ page_obj.paginator.num_pages }}"
我正在使用 django-filter
包在我的列表视图中提供搜索功能。
现在我也想为该视图添加分页。
我正在尝试将分页与过滤查询集相结合,但我不知道如何继续。
到目前为止,我已经在 views.py
上尝试了以下操作:
def search(request):
qs = local_url.objects.filter(global_url__id=1).all()
paginator = Paginator(qs, 25)
page = request.GET.get('page')
try:
pub = paginator.page(page)
except PageNotAnInteger:
pub = paginator.page(1)
except EmptyPage:
pub = paginator.page(paginator.num_pages)
url_filter = PublicationFilter(request.GET, queryset=qs)
return render(request, 'ingester/search_list.html', {'filter': url_filter, 'publication':pub})
据我了解,您的目标是对过滤后的查询集进行分页。如果是这样,您可以将 PublicationFilter 对象的 "qs" 属性 传递给 Paginator 构造函数:
def search(request):
qs = local_url.objects.filter(global_url__id=1).all()
url_filter = PublicationFilter(request.GET, queryset=qs)
paginator = Paginator(url_filter.qs, 25)
page = request.GET.get('page')
try:
pub = paginator.page(page)
except PageNotAnInteger:
pub = paginator.page(1)
except EmptyPage:
pub = paginator.page(paginator.num_pages)
url_filter = PublicationFilter(request.GET, queryset=qs)
return render(request, 'ingester/search_list.html', {'publication':pub})
url_filter.qs 包含筛选的查询集
url_filter.queryset 包含未过滤的查询集
要使用 Django 过滤器并对过滤结果进行分页,您可以执行以下操作:
为您的模型创建过滤器 class:
在
my_project/my_app/filters.py
:import django_filters class MyModelFilter(django_filters.FilterSet): class Meta: model = MyModel # Declare all your model fields by which you will filter # your queryset here: fields = ['field_1', 'field_2', ...]
每个
FilterSet
对象都有一个.qs
属性 其中包含 过滤查询集 你甚至可以 override it if you want.我们将分页
.qs
属性 的MyModelFilter
:在
my_project/my_app/views.py
:from . import filters from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger def my_view(request): # BTW you do not need .all() after a .filter() # local_url.objects.filter(global_url__id=1) will do filtered_qs = filters.MyModelFilter( request.GET, queryset=MyModel.objects.all() ).qs paginator = Paginator(filtered_qs, YOUR_PAGE_SIZE) page = request.GET.get('page') try: response = paginator.page(page) except PageNotAnInteger: response = paginator.page(1) except EmptyPage: response = paginator.page(paginator.num_pages) return render( request, 'your_template.html', {'response': response} )
给你!
PS_1: 我的 Django 过滤器,"plays" better with Django Rest Framework.
PS_2: 如果你打算使用 DRF,我已经写了一个关于如何在基于函数的视图中使用分页的例子,你可以很容易地结合一个 FilterSet
:
@api_view(['GET',])
def my_function_based_list_view(request):
paginator = PageNumberPagination()
filtered_set = filters.MyModelFilter(
request.GET,
queryset=MyModel.objects.all()
).qs
context = paginator.paginate_queryset(filtered_set, request)
serializer = MyModelSerializer(context, many=True)
return paginator.get_paginated_response(serializer.data)
这对我有用:
在我的模板中而不是使用这个
<li><a href="?page={{ i }}">{{ i }}</a></li>
我写了这个:
{% if 'whatever_parameter_you_use_to_filter' in request.get_full_path %}
<li><a href="{{ request.get_full_path }}&page={{ i }}"{{ i }}</a></li>
{% else %}
<li><a href="?page={{ i }}">{{ i }}</a></li>
{% endif %}
希望对您有所帮助:)
这里最重要的部分是如何在模板中构建 URL。
你可能有
{% if pages.has_previous %}
<li><a href="?page={{ pages.previous_page_number }}">Prev</a></li>
{% endif %}
如果您仅使用它在初始分页结果之间切换,这非常好。
但棘手的部分是当您使用 django-fitler
过滤器时,查询字符串('?' 之后的那部分)变得全新 key-values对,忽略你的 ?page=2
或类似的。
因此,要使分页与过滤结果一起使用,当您单击 "Next" 或 "Prev" 按钮时 - 在 django-fitler
的 key-values 中,您还需要通过&page=5
一对。
如@stathoula 所述,您需要检查查询字符串中是否已存在至少一个过滤字段。如果是,那么您需要使用已经存在的 key-value 对,然后是新的 &page=3
对。
这看起来很简单,但我不得不做一些小技巧,不要在用户点击箭头时在查询字符串中一遍又一遍地重复 &page=1
。
在我的例子中,我将 'title' 作为过滤器,所以我需要检查它是否已经存在。
这是我为我的项目所做的完美工作的片段。
templates/pagination.html
<div class="paginator">
{% with request.get_full_path as querystring %}
<ul class="pagination nav navbar-nav">
<!-- Previous page section -->
{% if pages.has_previous %}
{% if 'title' in querystring %}
{% if 'page' in querystring %}
<li class="paginator {% if pages.number == page %}active{% endif %}">
<a href="{{ querystring|slice:":-7" }}&page={{ pages.previous_page_number }}">Prev</a>
</li>
{% else %}
<li class="paginator {% if pages.number == page %}active{% endif %}">
<a href="{{ querystring }}&page={{ pages.previous_page_number }}">Prev</a>
</li>
{% endif %}
{% else %}
<li class="paginator {% if pages.number == page %}active{% endif %}">
<a href="?page={{ pages.previous_page_number }}">Prev</a>
</li>
{% endif %}
{% endif %}
<!-- All pages section -->
{% for page in pages.paginator.page_range %}
{% if 'title' in querystring %}
{% if 'page' in querystring %}
<li class="paginator {% if pages.number == page %}active{% endif %}">
<a href="{{ querystring|slice:":-7" }}&page={{ page }}">{{ page }}</a>
</li>
{% else %}
<li class="paginator {% if pages.number == page %}active{% endif %}">
<a href="{{ querystring }}&page={{ page }}">{{ page }}</a>
</li>
{% endif %}
{% else %}
<li class="paginator {% if pages.number == page %}active{% endif %}">
<a href="?page={{ page }}">{{ page }}</a>
</li>
{% endif %}
{% endfor %}
<!-- Next page section -->
{% if pages.has_next %}
{% if 'title' in querystring %}
{% if 'page' in querystring %}
<li class="paginator {% if pages.number == page %}active{% endif %}">
<a href="{{ querystring|slice:":-7" }}&page={{ pages.next_page_number }}">Next</a>
</li>
{% else %}
<li class="paginator {% if pages.number == page %}active{% endif %}">
<a href="{{ querystring }}&page={{ pages.next_page_number }}">Next</a>
</li>
{% endif %}
{% else %}
<li class="paginator {% if pages.number == page %}active{% endif %}">
<a href="?page={{ pages.next_page_number }}">Next</a>
</li>
{% endif %}
{% endif %}
</ul>
{% endwith %}
</div>
这里是视图,以防万一:
app/views.py
def index(request):
condo_list = Condo.objects.all().order_by('-timestamp_created')
condo_filter = CondoFilter(request.GET, queryset=condo_list)
paginator = Paginator(condo_filter.qs, MAX_CONDOS_PER_PAGE)
page = request.GET.get('page')
try:
condos = paginator.page(page)
except PageNotAnInteger:
condos = paginator.page(1)
except EmptyPage:
condos = paginator.page(paginator.num_pages)
return render(request, 'app/index.html', {
'title': 'Home',
'condos': condos,
'page': page,
'condo_filter': condo_filter,
})
这是一个工作示例:
为了增加答案,我还使用了 html 表以及 django-filters 和 Paginator。下面是我的视图和模板文件。需要模板标签以确保将正确的参数传递给分页 url.
search_view.py
from django.shortcuts import render
from app.models.filters_model import ApiStatusFilter
from app.models.api_status import ApiStatus
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from datetime import datetime, timedelta
def status(request):
all_entries_ordered = ApiStatus.objects.values().order_by('-created_at')[:200]
for dictionarys in all_entries_ordered:
dictionarys
apistatus_list = ApiStatus.objects.values().order_by('-created_at')
apistatus_filter = ApiStatusFilter(request.GET, queryset=apistatus_list)
paginator = Paginator(apistatus_filter.qs, 10)
page = request.GET.get('page')
try:
dataqs = paginator.page(page)
except PageNotAnInteger:
dataqs = paginator.page(1)
except EmptyPage:
dataqs = paginator.page(paginator.num_pages)
return render(request, 'status_page_template.html', {'dictionarys': dictionarys, 'apistatus_filter': apistatus_filter, 'dataqs': dataqs, 'allobjects': apistatus_list})
status_template.html
{% load static %}
{% load my_templatetags %}
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" type="text/css" href="{% static 'css/table_styling.css' %}">
<meta charset="UTF-8">
<title>TEST</title>
</head>
<body>
<table>
<thead>
<tr>
{% for keys in dictionarys.keys %}
<th>{{ keys }}</th>
{% endfor %}
</tr>
</thead>
<form method="get">
{{ apistatus_filter.form.as_p }}
<button type="submit">Search</button>
{% for user in dataqs.object_list %}
<tr>
<td>{{ user.id }}</td>
<td>{{ user.date_time }}</td>
<td>{{ user.log }}</td>
</tr>
{% endfor %}
</form>
</tbody>
</table>
<div class="pagination">
<span>
{% if dataqs.has_previous %}
<a href="?{% query_transform request page=1 %}">« first</a>
<a href="?{% query_transform request page=dataqs.previous_page_number %}">previous</a>
{% endif %}
<span class="current">
Page {{ dataqs.number }} of {{ dataqs.paginator.num_pages }}.
</span>
{% if dataqs.has_next %}
<a href="?{% query_transform request page=dataqs.next_page_number %}">next</a>
<a href="?{% query_transform request page=dataqs.paginator.num_pages %}">last »</a>
{% endif %}
</span>
</div>
</body>
</html>
my_templatetags.py
from django import template
register = template.Library()
@register.simple_tag
def query_transform(request, **kwargs):
updated = request.GET.copy()
for k, v in kwargs.items():
if v is not None:
updated[k] = v
else:
updated.pop(k, 0)
return updated.urlencode()
我花了一些时间才找到 DRYer 和更清洁的解决方案来解决这个问题,我认为最好的解决方案是使用模板标签的解决方案。
from django import template
register = template.Library()
@register.simple_tag
def relative_url(value, field_name, urlencode=None):
url = '?{}={}'.format(field_name, value)
if urlencode:
querystring = urlencode.split('&')
filtered_querystring = filter(lambda p: p.split('=')[0] != field_name, querystring)
encoded_querystring = '&'.join(filtered_querystring)
url = '{}&{}'.format(url, encoded_querystring)
return url
并在您的模板中
<a href="{% relative_url i 'page' request.GET.urlencode %}">{{ i }}</a>
- 简单又甜美,
- 使用这个,
pip install filter-and-pagination
- https://pypi.org/project/filter-and-pagination/
实施步骤
- 通过
pip install filter-and-pagination
安装包
- 通过
from filter_and_pagination import FilterPagination
在 view.py 中导入 FilterPagination
- 在您的函数中按照以下标准编写代码...
queryset = FilterPagination.filter_and_pagination(request, Customer)
serialize_data = CustomerSerializer(queryset['queryset'], many=True).data
resultset = {'dataset': serialize_data, 'pagination': queryset['pagination']}
- 在这段代码中
Customer
是Django模型& CustomerSerializer
是一个 DRF 序列化器 class
- 在结果集中它包含数据集和分页数据,采用这种格式(API 响应)link:https://github.com/ashish1997it/filter-pagination-dj#demo
- 对于 API 请求,请遵循 PostMan collection link: https://github.com/ashish1997it/filter-pagination-dj#postman 在 header 部分,它将采用一个参数并请求您根据您的要求
如果您仍然遇到任何困难,请与我联系:)
我对分页结果“记住 filter/query URL 参数”的方法:将当前 URL 参数作为上下文变量传递:
# views.py
class PublicationFilterView(FilterView):
model = Publication
filterset_class = PublicationFilter
paginate_by = 15
def get_context_data(self, *args, **kwargs):
_request_copy = self.request.GET.copy()
parameters = _request_copy.pop('page', True) and _request_copy.urlencode()
context = super().get_context_data(*args, **kwargs)
context['parameters'] = parameters
return context
# templates/path/to/pagination.html
<a href="?page={{ page_obj.next_page_number }}&{{ parameters }}">
Next
</a>
这个对我来说 100% 有效
views.py:
def search(request):
category=Category.objects.all()
try:
qs=request.GET["qs"]
products=Product.objects.filter(Q(name__icontains=qs) |Q(details__icontains=qs) | Q(category__name__icontains=qs) | Q(branch__child__icontains=qs) | Q(manufacturer__name__icontains=qs) | Q(color__name__icontains=qs)).distinct()
print(products)
search=f"qs={qs}"
except:
search=None
并在 HTML
<ul class="shop-p__pagination">
{% if products.has_provious %}
<li>
<a class="fas fa-angle-left" href="?page={{ products.previous_page_number }}&{search}"></a></li>
{% endif %}
{% for i in products.paginator.page_range %}
{% if products.number == i %}
<li class="is-active"><a href="?page={{i}}&{{search}}">{{i}}</a></li>
{% else %}
<li><a href="?page={{i}}&{{search}}">{{i}}</a></li>
{% endif %}
{% endfor %}
{% if products.has_next %}
<li>
<a class="fas fa-angle-right" href="?page={{ products.next_page_number }}&{{search}}"></a></li>
{% endif %}
</ul>
在get_context_data()
函数中:
form_submitted = 'csrfmiddlewaretoken' in self.request.GET
context['cleaned_full_path'] = '{}{}'.format(
self.request.get_full_path().split('&page' if form_submitted else '?page')[0],
'&' if form_submitted else '?'
)
然后,在您的模板中,加载类似
的内容<a href="{{ cleaned_full_path }}page={{ page_obj.paginator.num_pages }}"